1

我正在使用来自 React-Native 的 TabView,作为其中的一部分,我将两种状态用于两个不同的对象,如下所示。

const [routes, setRoutes] = React.useState([]);
const [sceneMap, setSceneMap] = React.useState({});

每当 TabView 获得焦点时,我都会在 useEffect 挂钩中调用一个函数。同样在这个钩子内部,我正在使用新值更改/重新分配这两种状态,如下所示

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});**
            }
        });
    }, []);

这是我的返回函数:

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 在两个状态都得到更新之前不要重新渲染?有没有办法这样做,或者我以错误的方式实施?请建议

只是为了解释更多考虑下面的输出:

当我重新启动应用程序时,Routes 和 Array 的值如下:

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",
]

正如我从第二个输出中看到的那样,Routes 的状态已更新为 3(导致重新渲染),但不是 Array 的状态。由于哪个 TabView 正在显示/抛出错误

错误:

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)
4

2 回答 2

1
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>
)};

您可以在此处查看它是如何工作的。对于工作,请参阅此链接https://stackblitz.com/edit/react-p7jrjv?file=Hello.js

您已经添加了两个不同的 useState 而是尝试像我所做的那样将它组合成一个并在按钮上的一组功能中一起更改它单击它会同时更改两个属性

于 2020-05-04T19:22:54.163 回答
0

“我如何通知 React-Native 在两个状态都得到更新之前不要重新渲染?”

状态更改后,您无法停止重新渲染。但是你可以做的是在你准备好渲染之前不要更新状态。

如果您将两个状态更新一起移动,以便它们同时更新并且它们之间没有任何异步获取,它应该像您期望的那样工作。

        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});
        }
于 2020-05-04T18:59:45.530 回答