【问题标题】:The value on the Context Provider doesn't changeContext Provider 的值不会改变
【发布时间】:2021-01-22 11:07:35
【问题描述】:

所以,我正在学习 React Context 并尝试通过为我的 React Native 应用程序创建身份验证状态来实现它。我试着关注这个Ben Awad's repo。这是我到目前为止所得到的:

// AuthContext.tsx
export const AuthContext = createContext<{
  user: null | string;
  login: () => void;
}>({
  user: null,
  login: () => {},
});

export const AuthProvider = ({ children }: Props) => {
  const [user, setUser] = useState<null | string>(null);
  const { user: contextUser } = useContext(AuthContext);

  return (
    <AuthContext.Provider
      value={{
        user,
        login: () => {
          setUser("My Name");
          console.log("Auth Provider pressed");
          console.log("user (state) " + user);
          console.log("contextUser (context) " + contextUser);
        },
      }}
    >
      {children}
    </AuthContext.Provider>
  );
};

// Navigation.tsx
export const Navigation = ({}: Props) => {
  const { user } = useContext(AuthContext);

  return (
    <AuthProvider>
        {user ? <HomeScreen /> : <Button />}
    </AuthProvider>

// Button.tsx
export const Button = ({}: Props) => {
  const { login } = useContext(AuthContext);

  return (
    <View>
        <Touchable
          onPress={login}
        >
          <Text style={styles.container}>Submit</Text>
        </Touchable>
    </View>
  )

AuthProvider 有 2 个值。从useState() 获得的user。并且,login 调用 setUser 以更改 useState() 上的 user 并因此应该更改第一个 Provider 值上的 user

按钮上的 onPress 将从 AuthProvider 调用 login()。 AuthProvider 上的login() 将触发setUseruseState() 上的user 值从null 更改为“My Name”。在这部分之前,它按预期工作。

但是,即使按钮成功更改了useState() 上的user 值。它不会更改上下文上的user(更改为contextUser 用于“调试”目的),无论我单击按钮多少次,contextUser 将始终为空。

Tl;dr:AuthProvider 上的用户值在按下按钮后不会改变。但是,useState 上的用户发生了变化。

那么,发生了什么?我做错了什么?任何人都知道如何解决这个问题?在过去的几个小时里,我一直在关注这个问题,并在谷歌上搜索了更多关于这个的信息。我的代码与他们的相似(我将我的代码与也使用上下文和身份验证的其他人的代码进行了比较),但不知何故,这段代码不起作用。

无论如何,在 Navigation 上,它也应该在 Context 上的用户值更改为非 null 后自动重新渲染(成为 HomeScreen)。我还没有测试它是否会工作(好吧,用户价值永远不会改变)。任何人都可以查看它,看看它是否也可以按预期运行?

【问题讨论】:

    标签: reactjs typescript react-native


    【解决方案1】:

    问题是您在组件 (Navigation) 中使用上下文 const { user } = useContext(AuthContext);,该组件不是 AuthProvider 的子组件。

    目前,您的导航组件仅接收上下文的默认状态。如果将console.log 添加到上下文默认状态的login 方法中,您将看到它已执行,而不是作为上下文值返回的上下文login 方法。例如:

    // AuthContext.tsx
    export const AuthContext = createContext<{
      user: null | string;
      login: () => void;
    }>({
      user: null,
      login: () => {
        // this will run if there is no context provider when being called
        console.log('i am not working as expected')
      },
    });
    

    但是,您的 Button 组件正在接收完整的上下文,因为它是 Provider 的子组件,并且正在更新状态。

    如果您将AuthProvider“向上移动”,使其成为Navigation 组件的父级,则导航组件也将接收更新后的上下文数据。

    例如:

    const Wrapper = () => (
      <AuthProvider> 
        <Navigation />
      </AuthProvider>
    )
    

    【讨论】:

    • 非常感谢!现在这是有道理的。我只是将 Navigation 包装在 Provider 中并将其放置在 App 中,现在它可以按预期运行!
    猜你喜欢
    • 1970-01-01
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-13
    • 2021-09-24
    • 1970-01-01
    • 2019-12-20
    相关资源
    最近更新 更多