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?
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).