reactjs

React Official Documentation Recommends Passing setState to Child Components


In the official React documentation, there's an example where the setState function is passed down to child components:

import { useState } from 'react';

function FilterableProductTable({ products }) {
  const [filterText, setFilterText] = useState('');
  const [inStockOnly, setInStockOnly] = useState(false);

  return (
    <div>
      <SearchBar 
        filterText={filterText} 
        inStockOnly={inStockOnly} 
        onFilterTextChange={setFilterText} 
        onInStockOnlyChange={setInStockOnly} />
      <ProductTable 
        products={products} 
        filterText={filterText}
        inStockOnly={inStockOnly} />
    </div>
  );
}

This approach seems to go against the principle of encapsulation because it allows child components to directly manipulate the parent’s state.

Usually, I create a handler function and pass it down to the child instead:

const handleChangeFilterText = (val) => {
  setFilterText(val);
};

<SearchBar onFilterTextChange={handleChangeFilterText} />;

I can also wrap the handler with useCallback if the child is wrapped with React.memo.

I’ve always thought that passing setState directly to children is a bad practice, but seeing it in the React documentation has made me question this belief.

I’d appreciate insights from the community and React developers: Is this a recommended practice, or should it generally be avoided?


Solution

  • Component props are the same as function parameters in JS. Pass a callback function parameter is common pattern in JS. It does not go against the principle of encapsulation.

    You can also think of component props as public APIs

    setState function is stable, you don't have to use useCallback create another stable function.

    The set function has a stable identity, so you will often see it omitted from Effect dependencies, but including it will not cause the Effect to fire.

    See Caveats

    React component can be stateful or stateless.

    Encapsulated components include: view, view logic, data (state, constants, enum), business logic.

    Another component don't know the implementation details of the encapsulated component. Can only use the encapsulated component via its props(public API).