当状态第一次更新时,componentWillReceiveProps不触发

时间:2019-03-31 10:16:03

标签: reactjs react-native react-redux

我有两个不相关的组件连接到redux。一个是按钮,另一个是应用程序的主屏幕。计划是在单击按钮时让HomeScreen知道。因此,我有一个动作和一个减速器来传递按钮的状态。除我第一次单击该按钮时HomeScreen没有收到更新外,此方法工作正常。我必须单击两次按钮才能使状态通过。

添加事件操作:

import { PLUS_INCIDENT } from './types';

export const plusIncident = pressed => (dispatch) => {
  console.log('2: action: ', pressed);
  dispatch({
    type: PLUS_INCIDENT,
    payload: pressed
  });
};

按钮组件:

// The action
import { plusIncident } from '../redux/actions/plusIncident';

import { connect } from 'react-redux';

class AddIncidentButton extends Component {
  handleAddButtonPress = () => {
    const { pressed } = this.state;
    const { plusIncident } = this.props;

    const btnState = !pressed;
    this.setState({ pressed: btnState });
    plusIncident(btnState);
  };
...

}
...
export default connect(
  null,
  { plusIncident }
)(AddIncidentButton);

减速器:

import { PLUS_INCIDENT } from '../actions/types';

const initialiState = {
  pressed: false
};

function inc(state = initialiState, action) {
  switch (action.type) {
    case PLUS_INCIDENT:
      return {
        ...state,
        pressed: !action.payload
      };
    default:
      return state;
  }
}

主屏幕: 仅在两次单击按钮后才调用componentWillReceiveProps方法。

class HomeScreen extends React.Component {
  state = {
    pressed: false
  };

 componentWillReceiveProps(nextProps) {
    const { pressed } = this.props;
    if (pressed !== nextProps.pressed) {
      this.setState({ pressed: !nextProps.pressed });
    }
  }
...
}

const mapStateToProps = state => ({
  pressed: state.inc.pressed
});
export default connect(mapStateToProps)(HomeScreen);

3 个答案:

答案 0 :(得分:2)

尝试添加也要首次调用的componentDidMount()。收到更新后将调用componentWillRecieveProps:

componentDidMount() {
      this.setState({ pressed: !this.props.pressed});
}

希望它能起作用。

答案 1 :(得分:0)

对于每个React docs,在初始安装期间将不会调用componentWillReceiveProps:

  

在安装过程中,React不会使用初始道具调用UNSAFE_componentWillReceiveProps()。仅当某些组件的道具可能会更新时才调用此方法。

无论如何,您都应避免使用componentWillReceiveProps,因为官方文档指出使用它经常会导致错误和不一致,并且在较新版本的React中不推荐使用它。


另一方面,当您将Redux状态复制到已订阅Redux存储的HomeScreen组件内的内部状态时,您将完全失去使用Redux的好处。

如果您需要根据 pressed 的值进行渲染,请在render方法内进行操作,这样,每次 pressed 的值,组件都会重新渲染。在调用某些Redux操作后更新:

class HomeScreen extends React.Component {

    render() {
        const pressed = this.props.pressed;

        <div>
            {pressed ? 'button is pressed' : 'button is not pressed'}
        </div>
    }

}



const mapStateToProps = state => ({
  pressed: state.inc.pressed
});
export default connect(mapStateToProps)(HomeScreen);

答案 2 :(得分:0)

在减速器中

import { PLUS_INCIDENT } from '../actions/types';

const initialiState = {
  pressed: false
};

function inc(state = initialiState, action) {
  switch (action.type) {
    case PLUS_INCIDENT:
      return {
        ...state,
        pressed: !action.payload  // remove this and add action.payload
      };
    default:
      return state;
  }
}

删除not(!)运算符。

希望这会有所帮助