Where should i place the provider redux?

喜夏-厌秋 提交于 2020-06-17 15:57:11

问题


I am new to React and i try to do a JWT authentication, but there are some incompatibilities between the tutorials i found and the new antd, which i want to use. As the errors shown below, i tried to add a Provider, but i probably didn't place it correctly Can you help me, please? Here is my login page:

import React from 'react';
import { Form, Icon, Input, Button, Spin } from 'antd';
import { connect } from 'react-redux';
import { NavLink } from 'react-router-dom';
import * as actions from '../store/actions/auth';
import { Provider } from 'react-redux'

const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;

class NormalLoginForm extends React.Component {
  handleSubmit = (e) => {
    e.preventDefault();
    this.props.form.validateFields((err, values) => {
      if (!err) {
        this.props.onAuth(values.userName, values.password);
        this.props.history.push('/');
      }
    });
  }

  render() {
    let errorMessage = null;
    if (this.props.error) {
        errorMessage = (
            <p>{this.props.error.message}</p>
        );
    }

    const { getFieldDecorator } = this.props.form;
    return (

        <div>
            {errorMessage}
            {
                this.props.loading ?

                <Spin indicator={antIcon} />

                :
                <Form onSubmit={this.handleSubmit} className="login-form">
                    <Form.Item name='userName' rules={[{ required: true, message: 'Please input your username!' }]}>
                        <Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
                    </Form.Item>

                    <Form.Item name="password" rules={[{ required: true, message: 'Please input your Password!' }]}>
                        <Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
                    </Form.Item>

                    <Form.Item>
                    <Button type="primary" htmlType="submit" style={{marginRight: '10px'}}>
                        Login
                    </Button>
                    Or 
                    <NavLink 
                        style={{marginRight: '10px'}} 
                        to='/signup/'> signup
                    </NavLink>
                    </Form.Item>
                </Form>

            }
      </div>

    );
  }
}

function mapStateToProps(state) {
    return {
        loading: state.loading,
        error: state.error
    }
}

function mapDispatchToProps(dispatch){
    return {
        onAuth: (username, password) => dispatch(actions.authLogin(username, password)) 
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(NormalLoginForm);

When i run it, i have some errors that say:

Error: Could not find "store" in the context of "Connect(NormalLoginForm)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(NormalLoginForm) in connect options.

and

he above error occurred in the <ConnectFunction> component:
    in ConnectFunction (created by Context.Consumer)
    in Route (at routes.js:12)
    in div (at routes.js:9)
    in BaseRouter (at App.js:15)
    in div (at Layout.js:23)
    in main (created by Basic)
    in Basic (created by Context.Consumer)
    in Content (at Layout.js:17)
    in section (created by Context.Consumer)
    in BasicLayout (created by Context.Consumer)
    in Layout (at Layout.js:8)
    in CustomLayout (at App.js:14)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:13)
    in div (at App.js:12)
    in App (at src/index.js:7)

Consider adding an error boundary to your tree to customize error handling behavior.

And also a warning:

Warning: React.createElement: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

Check your code at Login.js:55.

回答1:


I see you're importing { Provider }, but I don't think it's being used. Any components that you want to have access to state need to be wrapped in this component. For your code example, try the following:

return (
      <Provider>
        <div>
            {errorMessage}
            {
                this.props.loading ?

                <Spin indicator={antIcon} />

                :
                <Form onSubmit={this.handleSubmit} className="login-form">
                    <Form.Item name='userName' rules={[{ required: true, message: 'Please input your username!' }]}>
                        <Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
                    </Form.Item>

                    <Form.Item name="password" rules={[{ required: true, message: 'Please input your Password!' }]}>
                        <Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
                    </Form.Item>

                    <Form.Item>
                    <Button type="primary" htmlType="submit" style={{marginRight: '10px'}}>
                        Login
                    </Button>
                    Or 
                    <NavLink 
                        style={{marginRight: '10px'}} 
                        to='/signup/'> signup
                    </NavLink>
                    </Form.Item>
                </Form>

            }
      </div>
    <Provider />
    );

However, this looks like a single component of your app. Assuming there's more components that you want to have access to the Redux store, it's best practice to wrap the entire app in the Provider at the top level.




回答2:


Wrap Your Whole app using the Redux provider. You need to import your store from redux; And set your store to the provider and get the store data by using mapStateToProps from all your component.

return (
  <Provider store={store}>
    <div>
        {errorMessage}
        {
            this.props.loading ?

            <Spin indicator={antIcon} />

            :
            <Form onSubmit={this.handleSubmit} className="login-form">
                <Form.Item name='userName' rules={[{ required: true, message: 'Please input your username!' }]}>
                    <Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
                </Form.Item>

                <Form.Item name="password" rules={[{ required: true, message: 'Please input your Password!' }]}>
                    <Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
                </Form.Item>

                <Form.Item>
                <Button type="primary" htmlType="submit" style={{marginRight: '10px'}}>
                    Login
                </Button>
                Or 
                <NavLink 
                    style={{marginRight: '10px'}} 
                    to='/signup/'> signup
                </NavLink>
                </Form.Item>
            </Form>

        }
  </div>
<Provider />
);

Tips:

  1. You Can use Redux useSelector hook instead of mapStateToProps

  2. And Redux UseDispatch hook instead of mapDispatchToProps



来源:https://stackoverflow.com/questions/62288045/where-should-i-place-the-provider-redux

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!