I have a custom react hook:
function useItem(id) {
const [value, setValue] = useState();
useEffect(() => {
databaseRead(id).then(i => setValue(i));
}, [id]);
function setItem(i) {
setValue(i);
}
function writeItem(i) {
databaseWrite(id, i);
}
return [value, setItem, writeItem];
}
When using a hook like this in a component, the returned writeItem function changes every time the value changes (presumably because I create a new array every time).
How can I avoid re-renders of the Button component when I use my hook in an Item like so?
function Item(props) {
const [item, setItem, writeItem] = useItem(props.id);
return(
<>
<ItemEditor data={item} setItem={setItem}/>
<Button onPress={writeItem}/>
</>
)
}
My current working but awkward approach is to return a useRef object instead of the array from my hook:
function useItem(id) {
const retVal = useRef({
value: value,
setItem: setItem,
writeItem: writeItem
}).current;
const [dirty, setDirty] = useState();
function makeDirty() { setDirty(Math.random()); }
//and instead of setValue(i) do retVal.value=i; makeDirty();
return retVal;
}
Many thanks!
In addition, the custom hook returns the state and the functions to update the state in an array.
If we are going to be using multiple instances of a hook in a single component, then use array return. If our component will only have 1 (or few instances) of a hook, use object return. That's it!
Inspired by the concept of “partial application”, we can try to return a component with props that have been partially bound from a custom hook. However, the naive implementation will return new component definition when bound props changed, and that leads to unmount-remount behaviour that we may not expect.
By mastering the wrapper function, I finally solved my problem of how to add to an array in React state in three easy steps: Use useState([]) Hook to set state to [] and get state setter function. Pass wrapper function to state setter function (as a call-back function) Update array using .
A hook that has a very general use case benefits from exporting return values as an array. A great example of this is actually the built-in React.useState hook. Exporting an array makes it easy to customize the names of the state variables and their setters.
We can return multiple values in arrays or objects from a function and instantly destructure them. And, as you know, a React hook is just a convention-following function. const [one, two] = useNumbers() const { a, b, c } = useAlphabet() So why use one method over another?
Let’s get started. A custom Hook is a JavaScript function that begins with use. It is not mandatory to begin the custom Hook name with “use,” but without it, React would be unable to check for violations of the Hooks rules automatically. Therefore, it is critical to adhere to that naming convention.
The hook is expected to be used more than once in the same component. Although we can rename properties when destructuring an object, the simpler syntax for custom-named values returned from an array makes more sense. A hook that has a more specialized use case and returns a larger number of values may benefit by returning an object.
You can make use of useCallback
hook to memoize the functions so that they aren't created again on each render
function useItem(id) {
const [value, setValue] = useState();
useEffect(() => {
databaseRead(id).then(i => setValue(i));
}, [id]);
const setItem = useCallback(function(i) {
setValue(i);
}, []);
const writeItem = useCallback(function(i) {
databaseWrite(id, i);
}, [id]) // this depends on id, and need to be recreated on id change
return [value, setItem, writeItem];
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With