Вам необходимо правильно настроить редуктор и исходное хранилище, следуя документации Redux.
Вам не хватает Provider
, который предоставит ваш store
вашему приложению.
const store = createStore(reducer, applyMiddleware(thunk));
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
Теперь ваш магазин доступен вашим компонентам.
Вашему reducer
также необходимо начальное состояние, и вы всегда должны возвращать обновленную копию своего состояния. Тем не менее, не меняйте состояние напрямую, но сделайте копию, измените ее, а затем верните эту копию.
const initialState = {
name: ""
};
const reducer = function(state = initialState, action) {
if (action.type === "name") {
return { ...state, name: action.payload };
} else {
return state;
}
};
export default reducer;
Возможно, вы заметили, что я добавил промежуточное ПО в ваш магазин, и это потому, чтокак правило, при доступе к состоянию вашего текущего редуктора в ваших действиях. Тем не менее, для этого я установил redux-thunk, поэтому в вашем действии вы можете получить что-то вроде этого:
export const changeName = () => {
return (dispatch, getState) => {
if (getState().name === "Tarun") {
dispatch({ type: "name", payload: "Subhash" });
} else {
dispatch({ type: "name", payload: "Tarun" });
}
};
};
Теперь, когда ваш магазин предоставлен вашему приложению, ваш редуктор готов и ваши действиябудучи готовым к работе, вы можете подключить различные компоненты к вашему редуктору.
Для этого вы используете компонент высокого порядка в react-redux
, который называется connect
. Например, в вашем Name
компоненте мы можем подключить отображаемое имя к вашему редуктору, сопоставив свое состояние с подпорками компонента:
function Name(props) {
return <div>My name is: {props.name}</div>;
}
const mapStateToProps = state => {
return {
name: state.name
};
};
export default connect(mapStateToProps)(Name);
Приятно то, что вы также можете оставитьпервый параметр в connect
компоненте старшего разряда пуст и просто передайте второй, который будет функцией диспетчеризации. Что ж, это то, что вы сделали бы в своем App
компоненте, вы бы подключили его к действию changeName
.
function App(props) {
return (
<div>
<button onClick={props.changeName}>Click me</button>
<Name />
</div>
);
}
const mapDispatchToProps = dispatch => {
return {
changeName: () => dispatch(changeName())
};
};
export default connect(
null,
mapDispatchToProps
)(App);
Теперь, когда приложение отправляет действие changeName
, ваше состояние редуктора будетобновится, и остальные компоненты, подключенные к состоянию редуктора, будут перерисованы.
Резюме: попытайтесь представить свой магазин как пустую банку конфет. Ваша банка пуста, но различные действия могут изменить то, что находится внутри банки. Кроме того, разные люди в доме, которые знают, где находится банка, могут получить конфету. В переводе на вашу проблему, ваше приложение начинается с пустого имени, и у вас есть действие, которое устанавливает имя. Компоненты, которые знают, где найти это имя, будучи подключенным к вашему редуктору, будут знать, когда это имя изменится, и получат обновленное имя.
Окончательный код можно найти здесь: