简体   繁体   中英

Understanding Redux life cycle, (initial ajax load doesn't work)

Solved : defaultValue doesn't behave like I thought, I needed a controlled component, check React docs about Controlled Components.

What I want to do : load "owner" value in a form field after an Ajax call.

The problem is : "componentDidMount()" function doesn't update this.props.owner . The "owner" value is inside a Modal dialogue which appears when you click "Edit" in a list of rows in a previous component, after the second click all works perfectly, but not in the first load.

My AppoModal component:

class AppoModal extends Component {
  constructor(props) {
  super(props);
 }

 /** Load 'owner' in the form **/
 componentDidMount() {  
    let action = fetchAppos(this.props.routeParams.id);
   this.props.dispatch(action);
 }

 render() {
    return (
      <div>
        <input name="owner" defaultValue={this.props.owner} />
      </div>
     );
  }
 };

 AppoModal.propTypes = {
    owner: PropTypes.string.isRequired
 };
 AppoModal.defaultProps = {
    owner: 'incorrect initial props owner'
 };

 function mapStateToProps(state) {
  return {
     owner: state.rootReducer.appointments_rdcer.owner
  }
 }
 export default connect(mapStateToProps)(AppoModal); // binding React-Redux

my actions.js file:

 export function fetchAppos(appo_id=0) {
  return function (dispatch) {
    console.log('fecthAppos Action appo_id >>>>>' + appo_id);
    let data = {
      method: 'POST',
      credentials: 'same-origin',
      mode: 'same-origin',
      body: JSON.stringify({
       appoid: appo_id
      }),
      headers: {
       'Accept':       'application/json',
       'Content-Type': 'application/json',
       'X-CSRFToken':  cookie.load('csrftoken')
      }
    }
    return fetch('/appointments/get_appos', data)
       .then(response => response.json())  // promise
       .then(json = dispatch(receiveAppo(json)) )
    } 
   };
   // after fetchAppos, the API Ajax call
   function receiveAppo(appoArrayProp) {
     return {
       type:  GET_ONE_APPO,
       appoArrayProp: appoArrayProp.shift()
    }
  }

the reducer case:

case RECEIVE_ONE_APPO:
  return Object.assign({}, state, {
    owner:  action.appoArrayProp.owner
  });

Wrong result (should be "Grimms"):

在此处输入图片说明

So I defined "this.props.owner" as 'incorrect initial props owner' but, as far as I understand, componentDidMount should be executed after the whole DOM is loaded and then trigger:

this.props.dispatch(action)

and then the reducer should set "Grimms" as the value of this.props.owner, but this never happen. I see "Grimms" as the owner value in the reducer, so I don't follow why the this.props.owner is never updated.

In your render() function:

 render() {
    return (
      <div>
        <input name="owner" defaultValue={this.props.owner} />
      </div>
     );
  }

you use defaultValue, which is only used to set the value on the initial render (which in your case is with the defaultProps you specified). To update the value of the input, you must use a controlled <input> component .

Your <input> component becomes a controlled component simply by providing the value prop. Hence, defining your component like this should work:

 render() {
    return (
      <div>
        <input name="owner" value={this.props.owner} />
      </div>
     );
  }

See https://facebook.github.io/react/docs/forms.html for more info about controlled and uncontrolled components.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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