与 useSelector 混淆

Getting confused with useSelector

所以我想使用 react-redux 中的 connect 函数访问状态(使用 redux 进行状态管理)。

connect(mapStateToProps)(MyComponent)

但是当我尝试访问状态值时,它返回未定义。

然后,我所做的唯一更改是删除 connect 并使用 useSelector 挂钩引入我的组件并且它工作正常。

直到现在,我一直认为它们是相同的(在提供对状态的访问方面),但它的工作方式完全不同。

这是代码(我认为在这个问题的上下文中没有用,但也许我错了);

使用useSelector

const UnRegisteredStack = (props) => {
    const { token, verified } = useSelector((state) => ({
        token: state.token,
        verified: state.verified,
    }));
    return (
        <NavigationContainer>
            {token == null ? (
                <unRegistered.Navigator
                    initialRouteName="login"
                    screenOptions={{ headerShown: false }}
                >
                    <unRegistered.Screen name="login" component={Login} />
                    <unRegistered.Screen name="register" component={Register} />
                    <unRegistered.Screen name="passwordreset" component={PasswordReset} />
                </unRegistered.Navigator>
            ) : (
                <unRegistered.Navigator
                    initialRouteName="verifyemail"
                    screenOptions={{ headerShown: false }}
                >
                    {verified == null ? (
                        <unRegistered.Screen name="verifyemail" component={VerifyEmail} />
                    ) : (
                        <unRegistered.Screen name="details" component={Details} />
                    )}
                </unRegistered.Navigator>
            )}
        </NavigationContainer>
    );
};

使用connect

const UnRegisteredStack = (props) => {
    const { token, verified } = props;
    return (
        <NavigationContainer>
            {token == null ? (
                <unRegistered.Navigator
                    initialRouteName="login"
                    screenOptions={{ headerShown: false }}
                >
                    <unRegistered.Screen name="login" component={Login} />
                    <unRegistered.Screen name="register" component={Register} />
                    <unRegistered.Screen name="passwordreset" component={PasswordReset} />
                </unRegistered.Navigator>
            ) : (
                <unRegistered.Navigator
                    initialRouteName="verifyemail"
                    screenOptions={{ headerShown: false }}
                >
                    {verified == null ? (
                        <unRegistered.Screen name="verifyemail" component={VerifyEmail} />
                    ) : (
                        <unRegistered.Screen name="details" component={Details} />
                    )}
                </unRegistered.Navigator>
            )}
        </NavigationContainer>
    );
};

const mapStateToProps = (state) => ({
   token: state.token,
   verified: state.verified

})

connect(mapStateToProps)(UnRegisteredStack)

 

文档中省略的一个区别是,使用 useSelector 的组件使用更新的 React 钩子哲学,然后可以在不需要单独的包装器组件的情况下自行使用,而 connect(...)(UnRegisteredStack) 是使用较旧的通过将组件包装在包装器中来增加组件的哲学,例如:

const UnRegisteredStackHooks = (props) => {
    const { token, verified } = useSelector((state) => ({
        token: state.token,
        verified: state.verified,
    }));
    // rest of component
}

const UnRegisteredStackUnconnected = (props) => {
    // rest of component
}
const UnRegisteredStackConnected = connect(mapStateToProps)(UnRegisteredStackUnconnected);

const App = () => (
   <Provider store={store}>
      {/* Works ok */}
      <UnRegisteredStackHooks /> 
      {/* Needs the props passed */}
      <UnRegisteredStackUnconnected token={store.getState().token} />
      {/* Works ok */}
      <UnRegisteredStackConnected />
   </Provider>

);

这两种方法各有利弊。使用 connect,您可以保留一个组件的选项,该组件无需与 redux 耦合即可工作,因为您始终可以在没有 connect 的情况下导出组件并在其他地方引入连接。如果您不想创建模拟商店,这在测试时特别有用。

另一方面,hooks 使定义组件变得更加简单,如果需要测试,您可以随时模拟 hooks。