React钩子useEffect始终在React Navigation上重新渲染

时间:2020-03-04 12:13:44

标签: reactjs react-native react-hooks react-navigation

使用功能组件时,它们是createSwitchNavigator上的默认“页面”,导航至bottomTabNavigator后,如果状态发生了变化(不仅是在条件触发器发生变化时),整个组件将重新呈现,从而导致useEffect代码再次执行。

我的导航路线如下:

const Routes = createAppContainer(
  createSwitchNavigator({
    Sign: createSwitchNavigator({
      Preload,
      SignIn,
    }),
    App: createBottomTabNavigator(
      {
        Home,
        Employees,
      },
    ),
  }),
);

以及在SignIn和Home之间进行导航的功能组件:

const Preload = ({navigation, logged}) => {
    useEffect(() => {
        if (logged) {
            navigation.navigate({routeName: 'Home'});
        } else {
            navigation.navigate({routeName: 'SignIn'});
        }
    }, [logged]);

    return (
        <Container>
            <ActivityIndicator color="#1199DD" size={50}/>
        </Container>
    );
}

还注意到使用钩子有一个容器/页面连接器用于通量动作分配器:

const mapDispatchToProps = dispatch => ({
    actions: {
        ...appActions(dispatch),
        dispatch
    },
})

const mapStateToProps = state => ({
    ...state.app
})


export default connect(mapStateToProps, mapDispatchToProps)(Preload)

connect函数主要创建一个传递道具,分发和我的商店状态的消费者:

const isFunction = target => typeof target === 'function'
const defaultMapStateToProps = () => ({})
const defaultMapDispatchToProps = () => ({})

export default appContext => (originalMapStateToProps, originalMapDispatchToProps) => {

    const { Consumer } = appContext

    const mapStateToProps = isFunction(originalMapStateToProps)
        ? originalMapStateToProps
        : defaultMapStateToProps
    const mapDispatchToProps = isFunction(originalMapDispatchToProps)
        ? originalMapDispatchToProps
        : defaultMapDispatchToProps

    return Component => (props) => (
        <Consumer>
            {store => (
                <Component
                    {...props}
                    {...mapStateToProps(store.getState())}
                    {...mapDispatchToProps(store.dispatch)}
                />
            )}
        </Consumer>
    )
}

我尝试使用hook useRef来考虑最后一个值,但是由于它会重新呈现所有内容,因此最后一个值不受信任,因为它将始终重新创建此变量。

是什么真正触发了所有内容的重新渲染?绕过它的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

解决方案是放弃初始化一个Consumer的connect / container,因为我正在使用React Hooks来最好地发送初始化初始化useReducer时与分发有关的操作和状态。

下面的示例:

const [useContext, Provider] = createRootContext();

function createRootContext() {
    const RootContext = createContext(initialStateCombined);

    function useContext() {
        const c = React.useContext(RootContext);
        if (!c) throw new Error('');
        return c;
    }
    return [useContext, RootContext.Provider];
}

function RootProvider(props) {
    const [state, dispatch] = useReducer(appReducer, appInitialState);

    const actions = {
        app: {...appActions(dispatch)},
    };

    return <Provider value={{ state, actions }}>{props.children}</Provider>;
}

export { useContext, RootProvider };

这是我的提供者(作为应用程序的最高父级),我可以通过从状态导入useContext来访问该状态中的任何内容,例如:

const Preload = ({navigation}) => {
    const { state: { app } } = useContext();

    useEffect(() => {
        if (app.logged) {
            navigation.navigate('Home');
        } else {
            navigation.navigate('SignIn');
        }
    }, [app.logged])

    return (
        <Container>
            <ActivityIndicator color="#1199DD" size={50}/>
        </Container>
    )
}