上下文值的提供者不变

时间:2019-09-20 15:11:49

标签: reactjs typescript react-context

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

我要管理区域设置/身份验证。

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

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


             ClipRRect(
               borderRadius: BorderRadius.all(Radius.circular(10)),
               child: Container(
                        width: 400,
                        margin: EdgeInsets.only(top: 20),
                        padding: EdgeInsets.only(left: 10),
                        decoration: BoxDecoration(
                          border: Border(
                            left: BorderSide(
                                color: Color.fromRGBO(255, 167, 38, 1),
                                width: 5),
                            right: BorderSide(
                                width: .5,
                                color: Color.fromRGBO(116, 102, 102, .5)),
                            top: BorderSide(
                                width: .5,
                                color: Color.fromRGBO(116, 102, 102, .5)),
                            bottom: BorderSide(
                                width: .5,
                                color: Color.fromRGBO(116, 102, 102, .5)),
                          ),
                        ),

            )

现在的问题是,当我定义登录/注销功能并将其作为值传递给提供程序时,我的按钮将引发“尚未实现登录”错误。

这是我的代码:

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;

似乎新的登录/注销定义未在AuthContext中传递给提供程序。我可以肯定的是,我错过了ContextAPI的概念,而且我不明白背后的逻辑。感谢您的建议。

1 个答案:

答案 0 :(得分:0)

您需要添加具有新上下文的提供程序。 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>

); };