#reactjs #react-native #react-redux
#reactjs #react-native #реагировать-redux
Вопрос:
У меня есть два несвязанных компонента, подключенных к redux. Один из них — кнопка, а другой — рабочий стол приложения. План состоит в том, чтобы сообщить рабочему столу, когда нажата кнопка. Итак, у меня есть действие и редуктор для передачи статуса кнопки. Это работает нормально, за исключением того, что рабочий стол не получает обновления, когда я нажимаю кнопку в первый раз. Я должен дважды нажать кнопку, чтобы состояние завершилось.
Добавить действие инцидента:
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);
Ответ №1:
Попробуйте добавить componentDidMount(), который также будет вызываться в первый раз. componentWillReceiveProps будет вызван после получения обновления:
componentDidMount() {
this.setState({ pressed: !this.props.pressed});
}
Надеюсь, это сработает..
Комментарии:
1. Спасибо за ответ. Я не пробовал это, но это выглядит многообещающе. Третий ответ сработал для меня. Оказывается, я допустил ошибку в редукторе.
Ответ №2:
в вашем редукторе
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(!).
Надеюсь, это поможет
Комментарии:
1. Спасибо за ответ. Это сработало. Мне также пришлось удалить ‘pressed’ из состояния рабочего стола и вместо этого полагаться на props. т. Е. использовать this.props.pressed напрямую.
Ответ №3:
Согласно документам React, componentWillReceiveProps не будет вызываться во время первоначального монтирования:
React не вызывает UNSAFE_componentWillReceiveProps() с начальными реквизитами во время монтирования. Этот метод вызывается только в том случае, если некоторые реквизиты компонента могут обновиться.
В любом случае вам следует избегать использования componentWillReceiveProps, поскольку в официальной документации указано, что его использование часто приводит к ошибкам и несоответствиям, и он устарел в более новых версиях React.
С другой стороны, вы полностью упускаете преимущества использования Redux в вашем подходе, поскольку вы копируете состояние Redux в свое внутреннее состояние внутри компонента рабочего стола, который уже подписан на Redux store.
Если вам нужно отобразить что-либо на основе значения нажатой, сделайте это внутри метода визуализации следующим образом, и компонент будет повторно отображать каждый раз, когда значение нажатой обновляется после вызова некоторого действия 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);
Комментарии:
1. Спасибо за ответ. Это не начальное состояние, о котором я беспокоюсь. После нажатия кнопки я должен получить это первое обновление. Пожалуйста, смотрите ответ под этим.
2. Понял, рад, что вы разобрались с этим. При этом я по-прежнему рекомендую избегать дублирования состояния.