React Redux State显示init值而不是State值



我有点被一些React/Redux行为所困扰,我正在努力理解这些行为。我有一个带有选项卡界面的网页。每个选项卡式页面都包含几个子组件,例如搜索字段和一些顶级选项,然后用于从服务器获取数据并将其显示在下表中。我使用AGGrid作为表,一些单元格也包含单独渲染的组件。

在这种情况下,发生的情况如下:

  1. 我加载选项卡页面
  2. 选项卡式页面是用一个空的redux存储变量初始化的——表中没有信息,搜索字段中也没有显示任何内容
  3. 用户从搜索框列表中选择一个项目
  4. 现在,根据所选搜索,使用提取的服务器数据更新redux存储状态
  5. 该状态应保留在页面上。现在,如果我从表中调用一个函数(双击函数(,状态将显示初始化的值,而不是当前的存储的值但是,如果在尝试运行表函数之前在页面上执行任何其他操作,则会调用redux存储值,代码将按预期运行

以下是一些片段,因为代码太长,无法在此处重现。

这是从主页加载的初始选项卡页面:

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被设置为其初始化值(它们不是未定义的,也不是null,它们具有存储实例化中的初始化接口值(。

如果我与ProjectSearchForm组件上的任何其他元素交互,即使我的交互没有接触到商店,商店也会保留其值!我可以双击或在页面中进行任何其他导航,projectData将保持其状态。

我很不清楚这个问题的原因,如果我没有提供足够的信息来确定原因,我很抱歉。我已经设置了断点和useEffects来跟踪组件中projectData状态的更改,并且在更改存储后第一次与页面交互之前,没有迹象表明值会发生更改。

提前感谢您的任何见解!

编辑:我还想指出,在调试模式下,存储中的状态似乎不会发生变化。我正在Chrome中检查Redux调试器,并且该值已正确存储。只有在本地第一页交互中,存储变量(来自useSelector(才是不正确的。

我发现了这个。我可能(仍然(对底层函数指针和状态传递时的内存处理缺乏一些了解。本质上,似乎正在发生的是:

  1. 我正在将顶级功能传递给较低级别的组件
  2. redux存储值已更改
  3. 即使跟踪了存储值,较低级别的函数也没有更新
  4. 该函数是从较低级别调用的,但仍包含过时状态值

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

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

最新更新