componentWillReceiveProps не запускается при первом обновлении состояния - PullRequest
1 голос
/ 31 марта 2019

У меня есть два несвязанных компонента, подключенных к редуксу.Одна кнопка, а другая - домашний экран приложения.План состоит в том, чтобы сообщить 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;
  }
}

HomeScreen: вызывается только метод 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 ]

2 голосов
/ 31 марта 2019

Попробуйте добавить componentDidMount () также для вызова в первый раз. componentWillRecieveProps будет вызываться после получения обновления:

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

Надеюсь, что это работает ..

0 голосов
/ 31 марта 2019

в вашем редукторе

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 (!).

Надеюсь, это поможет

0 голосов
/ 31 марта 2019

Per React docs , componentWillReceiveProps не будет вызываться при первоначальном монтировании:

React не вызывает UNSAFE_componentWillReceiveProps () с начальными реквизитами во время монтирования. Он вызывает этот метод только в случае обновления некоторых реквизитов компонента.

В любом случае вам следует избегать использования componentWillReceiveProps, поскольку официальная документация гласит, что его использование часто приводит к ошибкам и несоответствиям, и в новых версиях React его не рекомендуется.


С другой стороны, вы полностью упускаете преимущества использования Redux с вашим подходом, поскольку вы копируете состояние Redux во внутреннее состояние внутри компонента HomeScreen, который уже подписан на хранилище Redux.

Если вам нужно визуализировать что-либо на основе значения нажатых , сделайте это внутри метода рендеринга следующим образом, и компонент будет перерисовываться каждый раз, когда значение нажатых обновляется после вызова какого-либо действия 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);
...