React-Redux状态显示初始值而不是状态值

mnemlml8  于 2022-11-12  发布在  React
关注(0)|答案(1)|浏览(183)

我在尝试理解React/Redux的一些行为时遇到了一些困难。我有一个带有选项卡式界面的网页。每个选项卡式页面都包含几个子组件--例如一个搜索字段和一些顶级选项,然后使用这些子组件从服务器获取数据并将其显示在下面的表中。我使用AG-Grid作为表,一些单元格也包含单独呈现的组件。
在这种情况下,会发生以下情况:
1.我加载选项卡页
1.选项卡页使用空redux-store变量初始化-表中没有信息,搜索字段中也没有要显示的内容
1.用户从搜索框列表中选择一项
1.现在,redux-store状态将根据所选搜索使用获取的服务器数据进行更新
1.该状态应该保留在页面上。现在,如果我从表中调用函数(双击函数),该状态显示的是初始化值,而不是当前的存储值。但是,如果我在尝试运行表函数之前在页面上执行 * 任何其他操作 *,则redux-store值将被调用,代码将按预期运行。
下面是一些代码片段,因为代码太长,无法在这里重现。
这是从主页加载的初始选项卡页:

const BuildProjectView = (props: {inputProjectObj: any}): JSX.Element => {
    const dispatch = useDispatch();
    const [selectedProject, setSelectedProject] = useState<Project>(projectEmptyObj);

    // fetch static data (once)
    useEffect(() => {
        //...fetch the background data required to display the page
    }, []);

    return(
        <React.Fragment>
            <BuildView inputProjectData={selectedProject}/>
            <BuildProjectTableView />
        </React.Fragment>  
    );
}

在这个例子中,selectedProject中没有要呈现的内容,我传入初始化状态。下面是BuildView代码:

const BuildView:React.FC<{inputProjectData: Project}> = (props) => {

    return (
        <Row>
            <Col xl={6} lg={6}>
                <ProjectSearchForm inputProjectData={props.inputProjectData}/>
            </Col>
            <Col xl={6} lg={6}>
                <FicMaterialSearchForm />
            </Col>
        </Row>

    );
}

现在,这里是ProjectSearchForm,redux存储在这里填充页面的其余部分:

const ProjectSearchForm = (props: {inputProjectData: Project}): JSX.Element => {
    const dispatch = useDispatch();
    //lots of other page state controllers here
    const projectData: Project = useSelector((state: RootState) => state.buildview.selectedProject);
    const selectedBuild: Build = useSelector((state: RootState) => state.buildview.selectedBuild);
    const [selectedProject, setSelectedProject] = useState(projectEmptyObj);
<...>

const projectChangeHandler = (event: any, value: Project | null): void => {
        if (value !== null) {
            dispatch(buildViewActions.setEditOption({editOption: false}));
            const projectId: number = value?.engagement;
            setSelectedProject(value);

            // determine project builds
            dispatch(getProjectBuildData(projectId));
        }
    }

    return (
        <React.Fragment>
            <Form>
                <Form.Group as={Row} controlId="projectSearchField">
                    <Form.Label column xl={1} lg={1} className="mr-1">Project:</Form.Label>
                    <Col xl={7} lg={7}>
                        <Autocomplete
                            <...Autocomplete field options here...>
                            onChange={projectChangeHandler}
                            value={selectedProject}
                        />
                    </Col>
               </Form.Group>
             </Form>
          </React.Fragment>

现在,我的Redux存储变量state.buildview.selectedProject已经更新。现在,我对上面呈现为空表的ProjectBuildTableView感兴趣。BuildProjectTableView包含许多表函数,这些函数由填充表的各种存储跟踪,以及表中呈现的组件。

const ProjectBuildTableView = (): JSX.Element => {
  //here I'm bringing in the Redux store component that is updated from the other view
  const projectData: Project = useSelector((state: RootState) => state.buildview.selectedProject);
  const selectedBuild: Build = useSelector((state: RootState) => state.buildview.selectedBuild);
  const openNewTabWhenCellDbClicked = (data: BuildItem | SerialItem, type: string): void => {
             const tabRequest = {
                tabId: type,
                tabChangeTrigger: true,
                inputObj: {
                    data: data, 
                    //EMPTY projectData!!
                    projectData: projectData,
                    selectedBuild: selectedBuild,
                    from: 'build'
                }
            }
            dispatch(commonActions.updateTabOptions({tabRequest: tabRequest}));
}

第一次加载页面后,我从搜索字段中选择了一些内容,并验证了数据已加载到存储中,我尝试双击表中的一个单元格,projectDataselectedBuild被设置为它们的初始化值(它们不是未定义的,也不是空值,它们具有来自存储示例化的初始化接口值)。
如果我与ProjectSearchForm组件上的 * 任何其他元素 * 进行交互,即使我的交互没有触及存储,存储也会保留其值!我可以双击或在页面中执行任何其他导航,projectData会保持其状态。
我不知道这个问题的原因,如果我没有提供足够的信息来确定原因,我很抱歉。我已经设置了断点和useEffects来跟踪组件中projectData状态的更改,* 直到 * 我在更改存储区后首次与页面交互时,才有任何值更改的迹象。
提前感谢您的任何见解!
编辑:我还想指出的是,在调试模式下,store中的状态似乎没有变化。我正在Chrome中检查Redux调试器,值被正确存储。只有在本地第一页交互中,store变量(来自useSelector)是不正确的。

irtuqstp

irtuqstp1#

我发现了这个问题。我可能(仍然)对底层函数指针和状态传递时的内存处理缺乏一些了解。本质上,似乎发生了什么:
1.我将顶级函数向下传递给较低级别的组件

  1. redux存储值已更改
    1.较低级别的函数未更新,即使跟踪了存储值
    1.已从较低级别调用该函数,但仍包含过时的状态值

解决方案:强制较低级别的函数重新呈现;* 在 * 状态值更新后重新发送更新的函数指针(通过useEffect强制渲染)

我希望其他人会发现这很有用,并意识到React缓存了整个函数,而不是通过引用传递它们。

相关问题