繁体   English   中英

如何使用反应钩子将 state 从子组件传递给父组件?

[英]How to use react hooks to pass a state from child component to the parent component?

我有如下的父组件。 这里我要设置子组件加载里面的setLoading function。

const ReportRechargeDetail = React.memo(() => {
  const [selectedDates, setSelectedDates] = useState([]);
const [loading, setLoading] = useState(false);
  const [isOpen, setIsOpen] = useState(false);
return (
    <>
       <Row className="header-wrapper">
        <div>
          Select date range to proceed : <Space />
          <RangePicker
            format="YYYY-MM-DD"
            onChange={onChange}
            disabled={loading}
            onOpenChange={onOpenChange}
            disabledDate={(currentDate) => currentDate.isAfter(moment())}

          />

        </div>
      </Row>
      { selectedDates ? (
        <Row className="header-wrapper">
          <div>
            <PrimeButton
              buttonName={"Download report"}
              onClick={onClickHeaderButton}
            />
          </div>
        </Row>
      ) : (<div></div>)
      }
      <Tabs defaultActiveKey="1" onChange={callback} type="card">
        <TabPane tab="IN APP" key="1">
          <GenerateReport
            columns={columns}
            reportType={"recharge-info/in-app"}
            reportName={"Recharge Details "}
            breadcrumbName={"RECHARGED_DETAILED_REPORT"}
            fileDownloadUrl={""}
            selectedDateRange={selectedDates}
            isOpen={isOpen}
            isLoadingCallBack={setLoading}
          />
        </TabPane>
        <TabPane tab="BALANCE" key="2">
          <GenerateReport
            columns={columns}
            reportType={"recharge-info/online"}
            reportName={"Recharge Details "}
            breadcrumbName={"RECHARGED_DETAILED_REPORT"}
            fileDownloadUrl={"Recharge"}
            selectedDateRange={selectedDates}
            isOpen={isOpen}
          />
        </TabPane>
      </Tabs>

    </>
  );
});

export default ReportRechargeDetail;


子组件如下。 但我收到一个错误,错误:无效的挂钩调用。 钩子只能在 function 组件的主体内部调用。 这可能由于以下原因之一而发生:

  1. 你可能有不匹配的 React 版本和渲染器(例如 React DOM)
  2. 您可能违反了 Hooks 规则
  3. 你可能在同一个应用程序中拥有多个 React 副本
const GenerateReport = React.memo(
    ({
        columns,
        reportType,
        reportName,
        breadcrumbName,
        fileDownloadUrl,
        downloadReport,
        downloadReportName,
        selectedDateRange,
        isOpen,
        isLoadingCallBack
    }) => {
        const [show, setShow] = useState(false);
        //const [isOpen, setIsOpen] = useState(false);
        const [pageNumber, setPageNumber] = useState(1);
        const [pageSize, setPageSize] = useState(10);
        const [selectedDates, setSelectedDates] = useState(selectedDateRange);
        const [performedActionList, setPerformedActionList] = useState([]);
        const [totalCount, SetTotalCount] = useState(0);
        const [loading, setLoading] = useState(false);
        const [requiredTotal, setRequiredTotal] = useState(true);
        const dispatch = useDispatch();

 const getRecurrentData = (dateStrings) => {
            isLoadingCallBack(true);
            setLoading(true);
            setShow(true);
 });
        };

return (
            <>
                {show ? (
                    <Spin spinning={loading}>
                        <ViewBoxBody
                            loading={loading}
                            showPrimaryButton={false}
                            columns={columns}
                            filterSearchBar={false}
                            dataSource={performedActionList}
                            onPaginationClick={onPaginationClick}
                            currentPage={pageNumber}
                            totalDataCount={totalCount}
                            pageSize={pageSize}
                            showSizeChanger={true}
                            onShowSizeChange={(curent, size) => setPageSize(size)}
                            hideOnSinglePage={false}
                            showTotal={(total) => {
                                return `Total ${total} items`;
                            }}
                        />
                        <ViewBoxFooter

                            onPaginationClick={onPaginationClick}
                            currentPage={pageNumber}
                            totalDataCount={totalCount}
                            pageSize={pageSize}
                            showSizeChanger={true}
                            onShowSizeChange={(curent, size) => setPageSize(size)}
                            hideOnSinglePage={false}
                            showTotal={(total) => {
                                return `Total ${total} items`;
                            }}
                        />
                    </Spin>
                ) : (
                    <div></div>
                )}
            </>
        );
    }
);

不要将setLoading传递给您的子组件,而是将钩子调用包装在父组件中用户定义的方法中。

...
const toggleLoading = (value) => {
  setLoading(value)
}
...
return ...

并在子组件的道具isLoadingCallBack={toggleLoading}中使用该方法。 根据复杂性,将父 state 包装在 Context [1] 中是有意义的,这样您就可以访问子树中任何位置的值/设置器。

[1] https://reactjs.org/docs/context.html

此错误有 3 个原因,如错误描述中所列

  1. 你可能有不匹配的 React 版本和渲染器(例如 React DOM)

  2. 您可能违反了 Hooks 规则

  3. 你可能在同一个应用程序中拥有多个 React 副本

让我们先选择 2 以确保我们遵循钩子规则

您的代码看起来不错,但让我们使用一小段工作代码,我们确信可以在您的环境中尝试它https://codesandbox.io/s/little-monad-0jo71?file=/src/App.js尝试此处的示例并将其放在单独的页面/路由中,如果它有效,那么问题将出在您的代码上,我们将在其中进行更多调查。

现在1号

你可能有不匹配的 React 版本和渲染器(例如 React DOM)

建议的解决方案:

仔细检查你的 react 和 react-dom 版本

现在3号

你可能在同一个应用程序中拥有多个 React 副本

建议的解决方案:

尝试本期https 中的解决方案://github.com/facebook/react/issues/13991

暂无
暂无

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

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