Do I need componentWillReceiveProps and replacePro

2019-07-13 03:23发布

i'm learning redux along side with react and did a first app to catch a few infos from Destiny and present for the user. The app has a select box where the user can choose one of the many activities and I save that activity to check with the API on the ActivityComponent, the problem is, I do that (get the activity identifier with redux and save on a store) then later I have to retrieve on the ActivityComponent but somehow I had to implement this:

componentWillReceiveProps(nextProps) {
    this.props = {};
    this.replaceProps(nextProps, cb => this.getAjax()); 
}

replaceProps(props, callback){
    this.props = Object.assign({}, this.props, props);
    this.setState(initialState);
    callback();
}

Well here's my repository on github if anyone could help me: https://github.com/persocon/destiny-weekly

4条回答
欢心
2楼-- · 2019-07-13 03:50

Generally speaking on life cycle of methods in react with redux. you should use redux methods. unless you have to use in react life cycle methods.

查看更多
Anthone
3楼-- · 2019-07-13 04:00

Yeah, I screwed up the comment haha sorry, on the SelectContainer.jsx now I'm doing that to retrieve the activity json after the select change:

const mapDispatchToProps = (dispatch) => {
    return {
        onSelectChange: (activity) =>{
            dispatch(changeApiUrl(activity));
            dispatch(findActivity(activity));
        }
    }
}

UPDATE

import { connect } from 'react-redux';
import { changeApiUrl, findActivity } from '../actions/index.jsx';
import ActivityComponent from '../components/ActivityComponent.jsx';

const mapStateToProps = (state) => {
    return state.activity;
}

export class ActivityContainer extends ActivityComponent {
    componentDidMount() {
        const { dispatch, identifier } = this.props;
        dispatch(findActivity(identifier));
    }
}

export default connect(mapStateToProps)(ActivityContainer);
查看更多
Explosion°爆炸
4楼-- · 2019-07-13 04:07

So the quick answer is no, it's not necessary. Why ? Well, you're not really using redux yet. If you look at that ajax call your are doing in replace props, getAjax, I inspected that in your codebase, and see you're calling setState in the component after receiving a request there.

With redux, you would rather use an action and reducer. The action would be handled, calling the api, and setting the state in the redux "store" with a reducer after receiving this data.

Ok so a full blown example would be something like the following, just first add in redux-thunk, it will definitely help you out going forward, be sure to go read through the example on the README to get a better idea of the how and why.

function startLoading() {
  return {
    type: 'LOADING_STARTED',
    isLoading: true
  }
}

function doneLoading(){
  return {
    type: 'LOADING_ENDED',
    isLoading: false
  }
}

function setActivity(result) {
  let lastGist = result[0];
  let activity = {
    identifier: result.display.identifier,
    title: (result.display.hasOwnProperty('advisorTypeCategory'))? result.display.advisorTypeCategory : '',
    name: (result.hasOwnProperty('details') && result.details.hasOwnProperty('activityName')) ? result.details.activityName : '',
    desc: (result.hasOwnProperty('details') && result.details.hasOwnProperty('activityDescription')) ? result.details.activityDescription : '',
    backgroundImg: (result.display.hasOwnProperty('image')) ? 'http://bungie.net' + result.display.image : '',
    modifiers: (result.hasOwnProperty('extended') && result.extended.hasOwnProperty('skullCategories')) ? result.extended.skullCategories : [],
    bosses: (result.hasOwnProperty('bosses')) ? result.bosses : [],
    items: (result.hasOwnProperty('items') && result.display.identifier == "xur") ? result.items : [],
    bounties: (result.hasOwnProperty('bounties')) ? result.bounties : []
  }
  return {
    type: 'SET_ACTIVITY',
    activity: activity
  }
}

export function findActivity(activity_id) {
 return dispatch => {
   dispatch(startLoading())
   $.get(activity_id, (result)=>{
     dispatch(doneLoading())
     if(response.status == 200){
       dispatch(setActivity(response.json))
     }else { 
       dispatch(errorHere)
     }
   })
 }
}

So it might look a bit intimidating at first, but after a go or two, it will feel more natural doing things this way, instead of in the component.

查看更多
别忘想泡老子
5楼-- · 2019-07-13 04:09

There shouldn't be any need for replaceProps, as the props will be updated automatically. componentWillReceiveProps is a chance for you to take a peek at what is to come in this lifecycle.

Note: You should never clobber this.props as that is used internally.

I would recommend comparing this.props to nextProps inside componentWillReceiveProps to see if the selected Activity has changed. If so, then fire the ajax call (which I recommend using a redux action passed into the component).

查看更多
登录 后发表回答