如何使用 useState 更新多个状态?
How to update the multiple state using useState?
我正在使用 React-Native 中的 TabView,作为其中的一部分,我正在为两个不同的对象使用两种状态,如下所示。
const [routes, setRoutes] = React.useState([]);
const [sceneMap, setSceneMap] = React.useState({});
只要 TabView 获得焦点,我就会在 useEffect 挂钩中调用一个函数。同样在这个钩子内部,我 changes/reassigning 具有新值的两个状态如下所示
React.useEffect(() => {
// Return the function to unsubscribe from the event so it gets removed on unmount
return navigation.addListener('focus', async () => {
const dynamicTabsResponse = await getTabsDynamically();
let response;
if (dynamicTabsResponse != null) {
response = await getRoutes(dynamicTabsResponse);
**setRoutes(response);**
const scenes = await getScenes(dynamicTabsResponse)
newSceneMap = await getSceneMap(response, scenes)
**setSceneMap({...newSceneMap});**
}
});
}, []);
这是我的 return 函数:
if (routes.length > 0 && Object.keys(newSceneMap).length > 0) {
return (
<TabView
navigationState={{index, routes}}
renderScene={SceneMap(sceneMap)}
onIndexChange={setIndex}
initialLayout={initialLayout}
/>
);
} else {
console.log( Object.keys(newSceneMap))
console.log("routes length", routes.length)
return null
}
问题是,一旦第一个状态更新,UI 就会重新渲染并导致错误,因为我的 UI 需要第二个状态的更新状态以及。我如何通知 React-Native 在两个状态都更新之前不要重新渲染?有没有办法这样做或者我以错误的方式实施?请推荐
只是为了解释更多,请考虑以下输出:
当我重新启动应用程序时,路由和数组的值如下:
1. routes length inside if 2
2. inside if Array [
"NEWS",
"CRIME",
]
当转到其他屏幕并选中复选框并来到Tabscreen时,输出如下:
1. routes length inside if 3
2. inside if Array [
"NEWS",
"CRIME",
]
正如我从第二个输出中看到的那样,路由的状态已更新为 3(这导致重新渲染),但阵列的状态并未更新。由于 TabView 是 displaying/throwing 错误
错误:
Check the render method of `SceneComponent`.,
in SceneComponent (created by SceneView)
in RCTView (created by SceneView)
in SceneView (created by Pager)
in RCTView (at createAnimatedComponent.js:233)
in AnimatedComponent(Component) (created by PanGestureHandler)
in PanGestureHandler (created by Pager)
in Pager (created by TabView)
in RCTView (created by TabView)
in TabView (at NewsScreen.js:73)
in NewsScreen (at SceneView.tsx:98)
in StaticContainer
in StaticContainer (at SceneView.tsx:89)
in EnsureSingleNavigator (at SceneView.tsx:88)
in SceneView (at useDescriptors.tsx:125)
in RCTView (at BottomTabView.tsx:38)
in SceneContent (at BottomTabView.tsx:122)
in RCTView (at ResourceSavingScene.tsx:44)
in RCTView (at ResourceSavingScene.tsx:27)
in ResourceSavingScene (at BottomTabView.tsx:117)
in RCTView (at screens.native.js:132)
in ScreenContainer (at BottomTabView.tsx:101)
in RCTView (at BottomTabView.tsx:100)
in SafeAreaProviderCompat (at BottomTabView.tsx:99)
in BottomTabView (at createBottomTabNavigator.tsx:41)
in BottomTabNavigator (at BottomTabNavigator.js:22)
in BottomTabNavigator (at SceneView.tsx:98)
in StaticContainer
in StaticContainer (at SceneView.tsx:89)
in EnsureSingleNavigator (at SceneView.tsx:88)
in SceneView (at useDescriptors.tsx:125)
in RCTView (at CardContainer.tsx:190)
in RCTView (at CardContainer.tsx:189)
in RCTView (at Card.tsx:526)
in RCTView (at createAnimatedComponent.js:151)
in AnimatedComponent (at Card.tsx:508)
in PanGestureHandler (at Card.tsx:501)
in RCTView (at createAnimatedComponent.js:151)
in AnimatedComponent (at Card.tsx:497)
"How can i inform React-Native not to re-render until both the states get update?"
状态更改后无法停止重新渲染。但是您可以做的是在您准备好渲染之前不更新状态。
如果您将两个状态更新移动到一起,那么它们会同时更新并且它们之间没有任何异步提取,它应该会像您预期的那样工作。
if (dynamicTabsResponse != null) {
response = await getRoutes(dynamicTabsResponse);
const scenes = await getScenes(dynamicTabsResponse)
newSceneMap = await getSceneMap(response, scenes)
// Update both states together, after all awaits are done.
setRoutes(response);
setSceneMap({...newSceneMap});
}
const Hello = () => {
let response = [{one:"two"}]
let newSceneMap = {
name:"sdfvsdf"
}
const [routesAndsceneMap, setIt] = React.useState({
routes:[{one:"three"}],
sceneMap:{
name:"sdfvds"
}
});
const changeit = () => {
setIt({...routesAndsceneMap,routes:[...response],sceneMap: {...newSceneMap}})
}
return (
<div>
<h1>Hello {routesAndsceneMap.routes[0].one} {routesAndsceneMap.sceneMap.name}!</h1>
<button onClick={changeit}>Click</button>
</div>
)};
你可以在这里查看它是如何工作的要查看这个linkhttps://stackblitz.com/edit/react-p7jrjv?file=Hello.js
您添加了两个不同的 useState 而不是像我所做的那样尝试将其合并为一个并在按钮上的一组函数中一起更改它单击它同时更改两个属性
我正在使用 React-Native 中的 TabView,作为其中的一部分,我正在为两个不同的对象使用两种状态,如下所示。
const [routes, setRoutes] = React.useState([]);
const [sceneMap, setSceneMap] = React.useState({});
只要 TabView 获得焦点,我就会在 useEffect 挂钩中调用一个函数。同样在这个钩子内部,我 changes/reassigning 具有新值的两个状态如下所示
React.useEffect(() => {
// Return the function to unsubscribe from the event so it gets removed on unmount
return navigation.addListener('focus', async () => {
const dynamicTabsResponse = await getTabsDynamically();
let response;
if (dynamicTabsResponse != null) {
response = await getRoutes(dynamicTabsResponse);
**setRoutes(response);**
const scenes = await getScenes(dynamicTabsResponse)
newSceneMap = await getSceneMap(response, scenes)
**setSceneMap({...newSceneMap});**
}
});
}, []);
这是我的 return 函数:
if (routes.length > 0 && Object.keys(newSceneMap).length > 0) {
return (
<TabView
navigationState={{index, routes}}
renderScene={SceneMap(sceneMap)}
onIndexChange={setIndex}
initialLayout={initialLayout}
/>
);
} else {
console.log( Object.keys(newSceneMap))
console.log("routes length", routes.length)
return null
}
问题是,一旦第一个状态更新,UI 就会重新渲染并导致错误,因为我的 UI 需要第二个状态的更新状态以及。我如何通知 React-Native 在两个状态都更新之前不要重新渲染?有没有办法这样做或者我以错误的方式实施?请推荐
只是为了解释更多,请考虑以下输出:
当我重新启动应用程序时,路由和数组的值如下:
1. routes length inside if 2
2. inside if Array [
"NEWS",
"CRIME",
]
当转到其他屏幕并选中复选框并来到Tabscreen时,输出如下:
1. routes length inside if 3
2. inside if Array [
"NEWS",
"CRIME",
]
正如我从第二个输出中看到的那样,路由的状态已更新为 3(这导致重新渲染),但阵列的状态并未更新。由于 TabView 是 displaying/throwing 错误
错误:
Check the render method of `SceneComponent`.,
in SceneComponent (created by SceneView)
in RCTView (created by SceneView)
in SceneView (created by Pager)
in RCTView (at createAnimatedComponent.js:233)
in AnimatedComponent(Component) (created by PanGestureHandler)
in PanGestureHandler (created by Pager)
in Pager (created by TabView)
in RCTView (created by TabView)
in TabView (at NewsScreen.js:73)
in NewsScreen (at SceneView.tsx:98)
in StaticContainer
in StaticContainer (at SceneView.tsx:89)
in EnsureSingleNavigator (at SceneView.tsx:88)
in SceneView (at useDescriptors.tsx:125)
in RCTView (at BottomTabView.tsx:38)
in SceneContent (at BottomTabView.tsx:122)
in RCTView (at ResourceSavingScene.tsx:44)
in RCTView (at ResourceSavingScene.tsx:27)
in ResourceSavingScene (at BottomTabView.tsx:117)
in RCTView (at screens.native.js:132)
in ScreenContainer (at BottomTabView.tsx:101)
in RCTView (at BottomTabView.tsx:100)
in SafeAreaProviderCompat (at BottomTabView.tsx:99)
in BottomTabView (at createBottomTabNavigator.tsx:41)
in BottomTabNavigator (at BottomTabNavigator.js:22)
in BottomTabNavigator (at SceneView.tsx:98)
in StaticContainer
in StaticContainer (at SceneView.tsx:89)
in EnsureSingleNavigator (at SceneView.tsx:88)
in SceneView (at useDescriptors.tsx:125)
in RCTView (at CardContainer.tsx:190)
in RCTView (at CardContainer.tsx:189)
in RCTView (at Card.tsx:526)
in RCTView (at createAnimatedComponent.js:151)
in AnimatedComponent (at Card.tsx:508)
in PanGestureHandler (at Card.tsx:501)
in RCTView (at createAnimatedComponent.js:151)
in AnimatedComponent (at Card.tsx:497)
"How can i inform React-Native not to re-render until both the states get update?"
状态更改后无法停止重新渲染。但是您可以做的是在您准备好渲染之前不更新状态。
如果您将两个状态更新移动到一起,那么它们会同时更新并且它们之间没有任何异步提取,它应该会像您预期的那样工作。
if (dynamicTabsResponse != null) {
response = await getRoutes(dynamicTabsResponse);
const scenes = await getScenes(dynamicTabsResponse)
newSceneMap = await getSceneMap(response, scenes)
// Update both states together, after all awaits are done.
setRoutes(response);
setSceneMap({...newSceneMap});
}
const Hello = () => {
let response = [{one:"two"}]
let newSceneMap = {
name:"sdfvsdf"
}
const [routesAndsceneMap, setIt] = React.useState({
routes:[{one:"three"}],
sceneMap:{
name:"sdfvds"
}
});
const changeit = () => {
setIt({...routesAndsceneMap,routes:[...response],sceneMap: {...newSceneMap}})
}
return (
<div>
<h1>Hello {routesAndsceneMap.routes[0].one} {routesAndsceneMap.sceneMap.name}!</h1>
<button onClick={changeit}>Click</button>
</div>
)};
你可以在这里查看它是如何工作的要查看这个linkhttps://stackblitz.com/edit/react-p7jrjv?file=Hello.js
您添加了两个不同的 useState 而不是像我所做的那样尝试将其合并为一个并在按钮上的一组函数中一起更改它单击它同时更改两个属性