为什么 React Context 只会从 DOM 元素触发传递的值函数



>我正在尝试使用 React Context 来更新我的 Web 应用程序的登录/注销功能。由于这不是一个要调用的高流量函数,我认为这是一个绝佳的机会来使用上下文 API,创建我的提供程序,并在链下的必要组件中利用提供程序。

不幸的是,我似乎不能在组件函数中使用任何传递的函数,例如 handleSubmit((。如果我直接从 DOM 元素调用它们,它们会很好地工作(下面的示例(。

我认为这是某种"这个"错误,并且 DOM 调用使用的范围与组件中的范围不同。

关于为什么会发生这种情况以及如何解决它的任何帮助都会很棒。

谢谢!

上下文:

export const LoginContext = React.createContext({});
export class LoginCtx extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isLoggedIn: false,
            login: () => this.login,
            logout: () => this.logout
        };
        this.login = this.login.bind(this);
        this.logout = this.logout.bind(this);
    }
    login(user) {
        console.log('Inside Login:', user);
        this.setState({ isLoggedIn: true });
    }
    logout() {
        console.log('Inside Logout');
        this.setState({ isLoggedIn: false });
    }
    render() {
        return (
            <LoginContext.Provider value={this.state}>
                {this.props.children}
            </LoginContext.Provider>
        );
    }
}

形式:

const C = ({ classes }) => {
    const { login } = useContext(LoginContext);
    const initialValues = {
        email: 'abc@test.com',
        password: '',
        remember: false
    };
    const dummySubmit = async (values, actions) => {
        console.log(JSON.stringify(values, null, 2));
        if (values.email === 'abc@test.com') {
            // THIS ONE WONT FIRE THE LOGIN COMMAND
            login();
        }
        actions.setSubmitting(false);
    };
    return (
        <React.Fragment>
            <Formik
                initialValues={initialValues}
                onSubmit={(values, actions) => dummySubmit(values, actions)}
            >
                {({ isSubmitting }) => (
                    <Form className={classes.form}>
                        <div>
                            <Field
                                name='email'
                                type='email'
                                placeholder='Email'
                            />
                            <ErrorMessage name='email' component='div' />
                        </div>
                        <div>
                            <Field
                                name='password'
                                type='password'
                                placeholder='Password'
                            />
                            <ErrorMessage name='email' component='div' />
                        </div>
                        <button type='submit' disabled={isSubmitting}>
                            Login
                        </button>
                    </Form>
                )}
            </Formik>
            {/* THIS ONE DOES FIRE THE LOGIN COMMAND */}
            <button onClick={login()}>Login Ctx</button>
        </React.Fragment>
    );
};
this.state = {
    isLoggedIn: false,
    login: () => this.login,
    logout: () => this.logout
};

您在此处创建的函数除了返回对 this.login/this.logout 的引用外,什么都不做。就目前而言,组件树中较远的组件必须调用它们从上下文中获取的函数,然后调用第一次调用返回的函数。例如:

const { login } = useContext(LoginContext);
// ...
login()();

最有可能的是,你要么打算这样做:

this.state = {
    isLoggedIn: false,
    login: () => this.login(),
    logout: () => this.logout()
};
this.login = this.login.bind(this);
this.logout = this.logout.bind(this);

或者这个:

this.login = this.login.bind(this);
this.logout = this.logout.bind(this);
this.state = {
    isLoggedIn: false,
    login: this.login,
    logout: this.logout
};

最新更新