0

I am facing a problem where calling forceUpdate on parent component doesn't re render the child component. I have attached the code snippets below.

PARENT COMPONENT

 const forceUpdate = React.useReducer(() => ({}))[1]; const getAccountDetails = () => { const opts = { mailboxKey: details.getMailboxKey() }; details.getAccountDetails(opts).then((response) => { if (response.resp.data.lastSyncTime && response.resp.data.lastSyncTime !== -1) { setLastSyncTime(response.resp.data.lastSyncTime); if (response?.resp?.data?.ssi) { details.set("ssi", response.resp.data.ssi); } if (response?.resp?.data?.fsi) { details.set("fsi", response.resp.data.fsi); } } details.set("isSyncCompleted", response.resp.data?.isSyncCompleted); }).catch((ex) => { succErrMsg(getI18N("ERROR"), { severity: "error", ...succErrMsgOption }); }); forceUpdate(); }; useEffect(() => { getAccountDetails(); }, []); const renderStatustable = () => { const isSyncCompleted = details.getIsSyncCompleted(); if (isSyncCompleted) { return <ImapSyncStatus {...{details}} />; } return <ImapFolderSyncStatus {...{details, getAccountDetails}} />; }; return (showSyncStatusTable && renderStatustable()) 

CHILD COMPONENT ImapFolderSyncStatus.js

const [fsiData, setFsiData] = useState(); useEffect(() => { setFsiData(details.getFolderSyncStatusInfo()); }, []); function renderFolderSyncStatusRows () { const rows = []; for (const key in fsiData) { if (Object.hasOwnProperty.call(fsiData, key)) { const element = fsiData[key]; rows.push( <Tr> <Td> {element.folderName} </Td> <Td> {element.ci.ZCount} </Td> <Td> {element.ci.mailCount} </Td> </Tr> ); } } return rows; } return (<> <ButtonColumn align="right"> <Button variant="flat" variantColor="primary" size="custom" onClick={getAccountDetails}> <Icon className="rotate-right" /> {getI18N("Refresh folder")} </Button> </ButtonColumn>{renderFolderSyncStatusRows()} </>); 

As u can see, I am calling the parent getAccountDetails function from child. The function gets called correctly and forceUpdate is also triggered. However if I add breakpoint on the line const [fsiData, setFsiData] = useState(); and inside the useEffect in child component, only the former breakpoint is triggered. I solved this by adding a key to the child component but I don't understand what exactly is going on.

3
  • If you need a forceUpdate function, your app is broken in some way, and will likely contain subtle, hard-to-debug bugs. Commented Sep 8, 2022 at 12:12
  • Yeah. Like I mentioned the fix is to add a unique key to the child component and it fixes the issue without forceUpdate. But I like to know why forceUpdate not rerendering. I guess it has to do something with object. But don't know exactly. Commented Sep 8, 2022 at 12:18
  • 1
    Well, see my answer. It explains what's wrong. Commented Sep 8, 2022 at 12:22

1 Answer 1

1

Your child component is updating just fine. It's just that the data you're seeing won't because of your misuse of useEffect.

With a component like

function Component(...) { const [fsiData, setFsiData] = useState(); useEffect(() => { setFsiData(details.getFolderSyncStatusInfo()); }, []); // ... use fsiData for rendering... } 

the effect is only ever run when the component mounts and never again.

The props changing doesn't cause the component to (re)mount, so the effect is never run and you're stuck with the same data. (The component's key changing will cause a remount.)

Just do

function Component(...) { const fsiData = details.getFolderSyncStatusInfo(); } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.