Как обновить компонент React после изменения состояния через Redux? - PullRequest
2 голосов
/ 05 октября 2019

Я изучал React и Redux и, делая это, я решил создать веб-страницу с кнопкой, которая при нажатии изменяла бы состояние. Под кнопкой я хотел отобразить текущее состояние в другом компоненте. Хотя кнопка при нажатии изменяет состояние, но она не отражается в компоненте. Вот мой код:

App.js

import React from 'react'
import Name from './Name'
import {changeName} from './Action'; 

export default function App () {  
      return (
          <div>
            <button onClick={changeName}>Click me</button>
            <Name />
          </div>
      )
}

Name.js

import React from 'react'
import {store} from './Store'

function Name(props) {
    return (
        <div>           
            My name is: {store.getState()}
        </div>
    )
}

export default Name

Store.js

import { createStore } from 'redux';
import {reducer} from './Reducer';

export const store = createStore(reducer, 'Tarun');

Action.js

import {store} from './Store';

export const changeName = () => {
    if (store.getState() === "Tarun"){
        store.dispatch({ type: 'name', payload: 'Subhash' });
    }
    else{
        store.dispatch({ type: 'name', payload: 'Tarun' });
    }
}

Reducer.js

export const reducer = function(state, action) {
    if (action.type === 'name') {
      return action.payload;
    }
    return state;
};

Когда я нажимаю кнопку, текст внутри компонента Name не изменяется. В чем проблема?

Ответы [ 2 ]

1 голос
/ 05 октября 2019

Вам необходимо правильно настроить редуктор и исходное хранилище, следуя документации 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, ваше состояние редуктора будетобновится, и остальные компоненты, подключенные к состоянию редуктора, будут перерисованы.

Резюме: попытайтесь представить свой магазин как пустую банку конфет. Ваша банка пуста, но различные действия могут изменить то, что находится внутри банки. Кроме того, разные люди в доме, которые знают, где находится банка, могут получить конфету. В переводе на вашу проблему, ваше приложение начинается с пустого имени, и у вас есть действие, которое устанавливает имя. Компоненты, которые знают, где найти это имя, будучи подключенным к вашему редуктору, будут знать, когда это имя изменится, и получат обновленное имя.

Окончательный код можно найти здесь:

Edit vigilant-field-shfj7

0 голосов
/ 05 октября 2019

Единственный способ, которым ваш компонент имени будет перерисован, это его реквизит или изменение состояния, или если родительский компонент перерисовывается. Изменение редукса автоматически не сделает этого. Чтобы увидеть изменения в состоянии, вам нужно подписаться на эти изменения. Вы можете сделать это самостоятельно, но гораздо лучшим решением будет использовать реаги-редукс , который предназначен для подключения компонентов реакции к хранилищам редуксов.

Например, вы бы добавили поставщикав ваше приложение:

import { Provider } from 'react-redux';
import { store } from './Store'

export default function App () {  
  return (
    <Provider store={store}>
      <div>
        <button onClick={changeName}>Click me</button>
        <Name />
      </div>
    </Provider>
  )
}

И тогда вы будете использовать connect с вашим компонентом имени:

import { connect } from 'react-redux';
function Name(props) {
  return (
    <div>           
      My name is: {props.name}
    </div>
  )
}

const mapStateToProps = (state) => {
  return { name: state };
}

export default connect(mapStateToProps)(Name)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...