【问题标题】:Provider from context value doesn't change上下文值的提供者不会改变
【发布时间】:2020-01-21 16:05:37
【问题描述】:

我正在尝试在一个新的 react+typescript 示例项目中学习 ContextAPI。

我想管理语言环境/身份验证。

我必须初始化我的上下文值(Typescript / eslint 需要),特别是登录/注销功能,或者“App.tsx”中出现错误:“无法调用可能未定义的对象”。

对,我尝试如下初始化我的上下文:

const AuthContext = React.createContext<ContextProps>({
    ...initialState,
    login: () => {
        throw new Error("login() not implemented yet");
    },
    logout: () => {
        throw new Error("logout() not implemented yet");
    }
 });

现在的问题是,当我定义登录/注销函数并作为值传递给我的提供者时,我的按钮会抛出“尚未实现登录”错误。

这是我的代码:

// ./App.tsx
import React from "react";
import { NavItem, Button } from "reactstrap";

import * as Context from "./contexts";

const App = () => {
      return (
      <Context.Language.Consumer>
        {({ locale, translation, switchLocale }) => (
            <Context.Auth.Consumer>
              {Auth => (
                  <NavItem right>
                    {Auth.isLoggedIn ? (
                        <Button onClick={() => Auth.logout()}>
                          {translation.logout}
                        </Button>
                    ) : (
                        <Button onClick={() => Auth.login()}>
                          {translation.login}
                        </Button>
                    )}
                  </NavItem>
              )}
            </Context.Auth.Consumer>
        )}
      </Context.Language.Consumer>
  );
};

export default App;

--

// ./contexts/AuthContext.tsx
import React, {Component} from "react";

type ContextProps = {
  isLoggedIn: boolean;
  login: () => void;
  logout: () => void;
};

const initialState = { isLoggedIn: false };
type Props = {};
type State = {} & typeof initialState;

const AuthContext = React.createContext<ContextProps>({
  ...initialState,
  login: () => {
    throw new Error("login() not implemented yet");
  },
  logout: () => {
    throw new Error("logout() not implemented yet");
  }
});

class AuthProvider extends Component<Props, State> {
   readonly state = initialState;

  login = () => {
    this.setState({
      isLoggedIn: true
    });
  };

  logout = () => {
    this.setState({
      isLoggedIn: false
    });
  };

  render() {
    return (
      <AuthContext.Provider
        value={{...this.state, login: this.login, logout: this.logout}}
      >
        {this.props.children}
      </AuthContext.Provider>
    );
  }
}

export const Consumer = AuthContext.Consumer;
export const Provider = AuthProvider;

最后:

// ./contexts/index.js
import * as Auth from "./AuthContext";
import * as Language from "./LanguageContext";

export { Auth, Language };

似乎新的登录/注销定义没有传递给 AuthContext 中的提供者。我很确定我错过了 ContextAPI 中的一个概念,而且我没有正确理解其背后的逻辑。感谢您的建议。

【问题讨论】:

    标签: reactjs typescript react-context


    【解决方案1】:

    您需要使用新上下文添加提供程序。 React 会向上查找第一个上下文提供者,如果没有,消费者获取默认值。

    const App = () => {
      return (
      <Context.Language.Consumer>
        {({ locale, translation, switchLocale }) => (
           <Context.Auth.Provider>
              <Context.Auth.Consumer>
                {Auth => (
                    <NavItem right>
                      {Auth.isLoggedIn ? (
                          <Button onClick={() => Auth.logout()}>
                            {translation.logout}
                          </Button>
                      ) : (
                          <Button onClick={() => Auth.login()}>
                            {translation.login}
                          </Button>
                      )}
                    </NavItem>
                )}
            </Context.Auth.Consumer>
          <Context.Auth.Provider>
        )}
      </Context.Language.Consumer>
    

    ); };

    【讨论】:

      猜你喜欢
      • 2020-09-05
      • 1970-01-01
      • 2019-07-10
      • 2023-03-21
      • 2022-11-19
      • 2020-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多