简体   繁体   English

反应子组件不会在父强制更新时重新渲染

[英]React child component not re-rendering on parent force update

I am facing a problem where calling forceUpdate on parent component doesn't re render the child component.我面临一个问题,即在父组件上调用 forceUpdate 不会重新渲染子组件。 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子组件 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.如您所见,我正在从孩子那里调用父getAccountDetails function。 The function gets called correctly and forceUpdate is also triggered. function 被正确调用并且 forceUpdate 也被触发。 However if I add breakpoint on the line const [fsiData, setFsiData] = useState();但是,如果我在const [fsiData, setFsiData] = useState();行上添加断点and inside the useEffect in child component, only the former breakpoint is triggered.而在子组件的useEffect里面,只会触发前一个断点。 I solved this by adding a key to the child component but I don't understand what exactly is going on.我通过向子组件添加一个键来解决这个问题,但我不明白到底发生了什么。

Your child component is updating just fine.您的子组件更新得很好。 It's just that the data you're seeing won't because of your misuse of useEffect .只是您看到的数据不会因为您滥用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.) (组件的key更改将导致重新安装。)

Just do做就是了

function Component(...) {
  const fsiData = details.getFolderSyncStatusInfo();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM