简体   繁体   English

Redux 存储更改后 React 组件不会更新

[英]React component doesn't update after Redux store change

These are my classes and component:这些是我的类和组件:

App.js:应用程序.js:

import { connect } from "react-redux";
import Main from "./components/main/Main";
import * as actions from "./redux/actions";
import { bindActionCreators } from "redux";
import { withRouter } from "react-router";

function mapStateToProps(state) {
  console.log(state);

  return {
    // naming must be exact same as function in reducer
    auth: state.auth,
    errorBag: state.errorBag
  };
}
function mapDispatchProps(dispatch) {
  return bindActionCreators(actions, dispatch);
}
const App = withRouter(connect(mapStateToProps, mapDispatchProps)(Main));
export default App;

Main.js:主要.js:

import React, { Component } from "react";
import { Redirect } from "react-router";
import { Route } from "react-router-dom";
import Login from "./../login/Login";
import Home from "./../home/Home";

class Main extends Component {

  render() {

    return (
      <div>
        <Route
          path="/login"
          render={param => {
            return <Login {...this.props} {...param} />;
          }}
        />

        {!this.auth ? <Redirect to="/login" /> : <Home />}
      </div>
    );
  }
}

export default Main;

reducer.js:减速器.js:

import { combineReducers } from "redux";

function authenticateReducer(state = null, action) {
  switch (action.type) {
    case "AUTHENTICATE": {
      return action.token;
    }
    default: {
      return state;
    }
  }
}
function errorBagReducer(state = [], action) {
  switch (action.type) {
    case "ADD_ERROR": {


      console.log("called");

      return { [action.area]: action.error };
    }
    default:
      return state;
  }
}

const rootReducer = combineReducers({ authenticateReducer, errorBagReducer });
export default rootReducer;

actions.js:动作.js:

import axios from "axios";

export function startSignUp(signUpData) {
  return dispatch => {

    return axios
      .post("http://localhost:8000/api/v1/user/sign-up/", signUpData)
      .then(res => {
        console.log(res);
        authenticate(res.data.shaba);
      })
      .catch(error => {
        console.log(error.data);
      });
  };
}
export function addErrorIntoBag(area, error) {
  return {
    type: "ADD_ERROR",
    area,
    error
  };
}


function authenticate(token) {
  return {
    type: "AUTHENTICATE",
    token
  };
}

Login.js:登录.js:

import React, { Component } from "react";
import "./login.css";
import InlineAlert from "./../alerts/InlineAlert";

class Login extends Component {
  constructor(props) {
    super(props);
  }
  getAreaName = () => "LOGIN";
  submitHandler = event => {
    event.preventDefault();
    const email = event.target.elements.email.value;
    const code = event.target.elements.code.value;
    const password = event.target.elements.password.value;
    if (password === "" || code === "" || email === "") {
      this.props.addErrorIntoBag(this.getAreaName(), "fill the form please");

      return;
    }
    const data = {
      email: email,
      password: password,
      national_code: code
    };
    this.props.startSignUp(data);
    this.forceUpdate();
  };
  render() {
    return (
      <div id="parent" onSubmit={this.submitHandler}>
        <form id="form_login">
          <h2>Login</h2>
          <br />
          <div className="form-group">
            <label forhtml="exampleInputEmail1">National code</label>
            <input
              key="code"
              type="text"
              className="form-control"
              id="exampleInputEmail1"
              aria-describedby="emailHelp"
              name="code"
            ></input>
          </div>
          <div className="form-group">
            <label forhtml="exampleInputPassword1">Email</label>
            <input
              type="email"
              className="form-control"
              id="email"
              name="email"
              key="email"
            ></input>
          </div>
          <div className="form-group">
            <label forhtml="exampleInputPassword1">Password</label>
            <input
              type="password"
              className="form-control"
              id="name"
              name="password"
              key="password"
            ></input>
          </div>
          <div className="form-group form-check"></div>
          <button type="submit" className="btn btn-light">
            SIGN-UP
          </button>
        </form>
        {/* drill down checking 🤯  */}
        {this.props.errorBag && this.props.errorBag[this.getAreaName()] && (
          <InlineAlert error={this.props.errorBag[this.getAreaName()]} />
        )}
      </div>
    );
  }
}

export default Login;

When I call submitHandler in Login.js and form is empty it calls an action to changes the redux store and Login.js component must update and InlieAlert component must appear in the screen, but anything doesn't change!当我在Login.js调用submitHandler并且表单为空时,它会调用一个操作来更改 redux 存储并且Login.js组件必须更新并且InlieAlert组件必须出现在屏幕中,但任何东西都不会改变!

Is it because of my Main.js that is middle of Login and Redux?是不是因为我的Main.js处于 Login 和 Redux 的中间?

I'm confused!我糊涂了!

I guess you forgot to call dispatch in startSignUp function.我猜你忘记在startSignUp函数中调用dispatch了。 It is not enough just to return from authenticate the object as you did with { type: "AUTHENTICATE", token } but you need to pass to dispatch also.仅像使用{ type: "AUTHENTICATE", token }那样从authenticate对象返回是不够的{ type: "AUTHENTICATE", token }但您还需要传递给dispatch In this way you are triggering a state change.通过这种方式,您正在触发状态更改。

From the documentation of dispatch(action) :dispatch(action)的文档中:

Dispatches an action.调度一个动作。 This is the only way to trigger a state change.这是触发状态更改的唯一方法。

Maybe you could try to do somehow the following:也许您可以尝试以某种方式执行以下操作:

export function startSignUp(signUpData) {
  return dispatch => {
    return axios
      .post("http://localhost:8000/api/v1/user/sign-up/", signUpData)
      .then(res => {
        console.log(res);
        // missing dispatch added
        dispatch(authenticate(res.data.shaba));
      })
      .catch(error => {
        console.log(error.data);
      });
  };
}

So you can think of like calling as the following at the end for the state change:所以你可以想像在状态改变的最后调用如下:

dispatch({
  type: "AUTHENTICATE",
  token
});

I hope this helps!我希望这有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM