The Five Tiny React Patterns I Type Without Thinking

Cheat sheet of the small React tricks I keep typing. Inline-style composition, args-to-handlers, SVG-as-component, and a JSON debug helper that has saved me three Saturdays.

JavaScript
Frontend
4 snippets
react
hooks
js-spread-rest
ryanjoshi

By @ryanjoshi

February 28, 2026

·

Updated May 18, 2026

482 views

8

4.3 (12)

// Combine multiple style objects with object spread, and pass everything else
// through to the underlying DOM node so callers can add data-* / aria-*
// without adding another prop. The gotcha at the bottom: React DOM warns
// (and strips) unknown attributes when you spread arbitrary props onto a
// host element, so the props need to be either DOM-valid or filtered out.
const { createElement } = (typeof React !== 'undefined' ? React : {
    createElement: (type, props, ...kids) => ({ type, props: props || {}, children: kids }),
});

const baseStyle = { padding: '8px 12px', borderRadius: 4, fontWeight: 500 };
const variantStyle = {
    primary: { background: '#2b6cb0', color: 'white' },
    danger:  { background: '#c53030', color: 'white' },
    ghost:   { background: 'transparent', color: '#2b6cb0' },
};
const stateStyle = {
    disabled: { opacity: 0.5, cursor: 'not-allowed' },
};

function Button(props) {
    const { variant, disabled, style, children, ...rest } = props;
    // Order matters: per-call `style` wins over the variant, which wins over base.
    const composed = Object.assign(
        {},
        baseStyle,
        variantStyle[variant] || variantStyle.primary,
        disabled ? stateStyle.disabled : null,
        style || null
    );
    return createElement('button', Object.assign({ style: composed, disabled }, rest), children);
}

console.log(JSON.stringify(Button({
    variant: 'primary', children: 'Save', 'aria-label': 'save form', 'data-testid': 'save-btn',
}), null, 2));

console.log('per-call style override beats variant:');
const overridden = Button({ variant: 'danger', style: { background: 'rebeccapurple' }, children: 'Hi' });
console.log('background:', overridden.props.style.background, '(per-call wins)');

// The gotcha: spreading non-DOM props onto a host element. React would warn
// about `loadingState` here, but we have stripped it out via destructuring
// and only rest-spread `aria-*` / `data-*` / event handlers.
const { loadingState, ...domSafe } = { loadingState: 'idle', 'aria-busy': 'false', onClick: () => {} };
console.log('non-DOM prop separated:', loadingState);
console.log('DOM-safe rest:', Object.keys(domSafe).join(', '));

The pattern is older than hooks but I still type it weekly. Compose with Object.assign({}, base, variant, state, override) rather than re-implementing CSS specificity by hand; the spread order is the cascade, and a per-call style always wins. The destructure-then-spread idiom is what makes the component a good citizen on the DOM: pulling out the props that belong to the component logic (variant, disabled, loadingState) and rest-spreading the rest preserves all the call-site aria-*, data-*, and event handlers without you maintaining an enumerated allowlist. The constructor pattern from the legacy snippet collection is the same idea in a class context, with this.props taking the place of the destructure.