Redux properties are not updated

-1

can help me not update the decorator's properties until after another dispacth takes the value. I do not know what's wrong.

@connect((store) => {
  return {
    adminLogin:store.adminLogin.error
  };
})

class Login extends React.Component {
  constructor(props){
    super(props)

    this.state={
      errors:{},
      user:{
          email:'',
          password:''
        }
    }
    store.subscribe(()=>{
      console.log(this.props.adminLogin)
      this.setState({
        errors:store.getState().adminLogin.error
      })
    })
    this.home = this.home.bind(this);
    this.onChange = this.onChange.bind(this);
    this.processForm = this.processForm.bind(this);
  }




  home(){
    this.props.history.push('/')
  }

  onChange(e){
    const user = this.state.user;
    const name = e.target.name;
    user[name] = e.target.value;

    this.setState({
      user
    })

  }



  processForm(event) {
    event.preventDefault();

      // create a string for an HTTP body message
    const email = encodeURIComponent(this.state.user.email);
    const password = encodeURIComponent(this.state.user.password);
    const formData = 'email=${email}&password=${password}';

     this.props.dispatch(postLogin(formData))

   }




  render() {
    return (<LoginCompo
              onSubmit={this.processForm}
              home={this.home}
              user={this.state.user}
              onChange={this.onChange}
              errors={this.state.errors}
             />);
  }

}

export default Login;

export function postLogin(formData) {

   return function(dispatch){
     const xhr = new XMLHttpRequest();
     xhr.open('post', '/auth/login');
     xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
     xhr.responseType = 'json';
     xhr.onload = () => {
       if (xhr.status === 200) {
         localStorage.setItem('admin',xhr.response.token)
         dispatch({type:'SAVE_TOKEN',token:xhr.response.token})
       } else {
         dispatch({type:'ERROR_LOGIN',error:xhr.response.errors})
       }
     };
     xhr.send(formData);
  }
}

export default function reducer(state={
    token:'',
    error:{},
  }, action) {

    switch (action.type) {
      case "SAVE_TOKEN": {
        return {...state, token: action.token}
      }
      case "ERROR_LOGIN":{
        return {...state, error:action.error}
      }
    }

    return state
}
    
asked by vale ale 12.07.2017 в 08:00
source

1 answer

0

I suppose you should know that the utility connect receives three functions, the first one -the one you are using- maps your subscription to a part of the store to properties that will be passed to the component. That said, you do not need to have in the state of the component a variable errors because these you will get from the store.

  

A component in React, whether stateless or stateful, is re-rendered if the props change from the outside.

To understand well how the integration between Redux and React works, look at the following diagram:

Commo you can see, every time the store is updated, the component subscribed to that part of the store that has been updated, receives an update of said store properties in the form of React props, forcing it to re-render.

Inside your code, both the action and the reducer are correct (it always returns the store by default in a default case ). The problem lies in your component; which should look like this:

@connect((store) => ({
  errors: store.adminLogin.error
})
class Login extends React.Component {
  constructor(props){
    super(props)
    this.state = {
      user:{
        email:'',
        password:''
      },
    };
    this.home = this.home.bind(this);
    this.onChange = this.onChange.bind(this);
    this.processForm = this.processForm.bind(this);
  }

  home(){
    this.props.history.push('/')
  }

  onChange(e){
    const user = this.state.user;
    const name = e.target.name;
    user[name] = e.target.value;
    this.setState({ user });
  }

  processForm(event) {
    event.preventDefault();

    // create a string for an HTTP body message
    const email = encodeURIComponent(this.state.user.email);
    const password = encodeURIComponent(this.state.user.password);
    const formData = 'email=${email}&password=${password}';
    this.props.dispatch(postLogin(formData));
  }

  render() {
    return (
      <LoginCompo
        onSubmit={this.processForm}
        home={this.home}
        user={this.state.user}
        onChange={this.onChange}
        errors={this.props.errors}
      />
    );
  }
}

Notice how we passed the prop errors that we received directly from the store to the <LoginCompo /> component. This will allow, when something bad happens in the request and the store updates and returns the errors as props for <Login /> , it is re-rendered and passed directly to the <LoginCompo /> component; showing the errors that have occurred.

As a final recommendation, use the new API Fetch for AJAX requests ( here you have a polyfill) and asynchronous functions / async-await for better control of your code.

    
answered by 12.07.2017 / 20:24
source