Drex
Drex

Reputation: 3851

React custom hook useState initialization value not update through outside props

I have a custom hook that has a locale state value by using useState, and I set the initial value from outside props, but when my props changes, my internal state value didn't get updated, in addition I am not quite understanding that, how many instance of custom hook in my component or application lifecycle where each time it's been triggered?

Here is the code example:

// custom hook
const useCustomHook = (initValue) => {
   const [isFetching, setIsFetching] = useState(initValue);

   useEffect(() => {
      console.log('initValue :>> ', initValue, ', isFetching :>>', isFetching);
   }, [initValue, isFetching);
}
// component
const myComponent = (props) => {
   const [shouldTrigger, setShouldTrigger] = useState(false);

   useCustomHook(shouldTrigger);

   onButtonClick = () => {
     setShouldTrigger(true);
   }
}

Here are the console logs that I get,

// when my component mouts
'initValue :>> ', false, ', isFetching :>>', false
// when button clicked
'initValue :>> ', true, ', isFetching :>>', false

as you can see, as long as I set my shouldTrigger to true from the main component, my custom hook gets invoked, however, the local state value isFetching inside my custom hook value is still false, shouldn't it be true as it'll be assigned from outside props every time? and is my above two useCustomHook the same instance or different? If there are different instance being called, why the second instance not set initial value as "true"?

Here is the code link https://stackblitz.com/edit/react-yma5my?file=index.js

Upvotes: 0

Views: 597

Answers (1)

Boykov
Boykov

Reputation: 374

  1. I'm not sure but I think it's because if you use useState you can define this value only once.
  2. and is my above two useCustomHook the same instance or different they will be different.

You can rewrite your code to

// custom hook
const useCustomHook = (initValue) => {
   const [isFetching, setIsFetching] = useState(initValue);

   useEffect(() => {
      console.log('initValue :>> ', initValue, ', isFetching :>>', isFetching);
   }, [initValue, isFetching);
  return [isFetching, setIsFetching]
}
// component
const myComponent = (props) => {
   const [isFetching, setIsFetching] = useCustomHook(false);

   onButtonClick = () => {
     setIsFetching(true);
   }
}

UPDATE

I just got an idea how to write in style that you wanted from start, but my first suggestion still better(as i think)

// custom hook
const useCustomHook = (value) => {
   const [isFetching, setIsFetching] = useState(value);

   useEffect(() => {
     setIsFetching(value);
   }, [value]);

   useEffect(() => {
      console.log('value :>> ', value, ', isFetching :>>', isFetching);
   }, [initValue, isFetching);
}
// component
const myComponent = (props) => {
   const [shouldTrigger, setShouldTrigger] = useState(false);

   useCustomHook(shouldTrigger);

   onButtonClick = () => {
     setShouldTrigger(true);
   }
}

It cause additional calling of setState but implements updating of state based on input props;

Upvotes: 1

Related Questions