0

I've a parent-child component structure, where parent fetches data to be displayed and child component displays the data. I want to update parent's state from child component. I'm sending a handler function from parent to the child as a prop, which is invoking the parent's handler function. Inside the parent's handler function, I'm updating state, however, that is not getting updated. Here is what I've done so far:

Parent Component:

const [startTime, setStartTime] = useState(new Date());

const myHandler = () => {
    const tn = new Date();
    setStartTime(tn);
    console.log(tn, startTime);
}
return (
    <ChildComponent myHandler={myHandler} />
);

Child Component:

interface Props {
  myHandler:(params: any) => any;
}

const someAction = useCallback(
    (studentId: Student['id']) => () => {
      navigation.push(STUDENTROUTE, { studentId });
      myHandler(studentId);
    },
    [navigation]
);

As output Tue Sep 11 2022 10:59:42 GMT-0400 (Eastern Daylight Time) is the time at which the state was initialized, and on subsequent calls, it never gets updated. Following is the output in Chrome debugger:

Tue Sep 11 2022 10:59:47 GMT-0400 (Eastern Daylight Time) Tue Sep 11 2022 10:59:42 GMT-0400 (Eastern Daylight Time)
Tue Sep 11 2022 11:00:06 GMT-0400 (Eastern Daylight Time) Tue Sep 11 2022 10:59:42 GMT-0400 (Eastern Daylight Time)

What am I doing wrong here? Do I have to use useEffect() hook here to update the state? If yes, how can I use it in this scenario of child updating parent's state?

SJaka
  • 712
  • 13
  • 40

1 Answers1

1

your problem is happening here

const myHandler = () => {
    const tn = new Date();
    setStartTime(tn);
    console.log(tn, startTime);
}

you are setting the state and trying to log it directly which doesn't work in react native, as react native takes a snapshot of the state on every render, so changes to the state will not be reflected until the next render.

basically, your state is being updated correctly, but trying to use or log the value directly will not work as it will only be able to access the old snapshot. (if you really need to use the value directly, then just use the tn variable you already have instead)

RodSar
  • 1,211
  • 1
  • 4
  • 14
  • Thanks for your detailed reply. I was trying to capture an update on the parent screen with a list, when I come back from the child. Is there a way instead to capture at the parent that the user has come back from the child component? – SJaka Sep 13 '22 at 18:51
  • Child has a `< Back` link at the top of the screen, which when pressed, takes the user to the parent screen. It is at that instance that I want to refresh the list of components at the parent level. I've a useEffect(() => { code }, [ ]); but when I go back from child component, this doesn't run. – SJaka Sep 13 '22 at 19:00
  • 1
    the effect doesn't run because the component did not unmount and mount again, and instead was just "hidden" behind your current screen in the stack until you navigate back . if you're using react-navigation to navigate back to the previous screen you can use useFocusEffect(useCallback(()=>{code},[])) instead which runs when you navigate back to the screen. – RodSar Sep 13 '22 at 19:15
  • Although useFocusEffect() works as intended, test cases in Jest is failing with error stating "couldn't find navigation object". Here is the question I created for it: https://stackoverflow.com/questions/73711952/react-native-jest-test-failing-upon-use-of-usefocuseffect-error-couldnt-f – SJaka Sep 14 '22 at 05:39