Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update React component after changing state through redux?

I was learning React and Redux and while doing that I decided to make webpage with a button which on clicking would change the state. Below the button I wanted to display the current state in a different component. Though the button on clicking changes the state, but it is not getting reflected in the component. Here is my code:

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;
};

When I click the button, The text inside the Name component does not change. What is the issue?

like image 291
Tarun Khare Avatar asked Oct 05 '19 15:10

Tarun Khare


People also ask

How do I reload component in Redux state change?

You need to create a selector and use it in your component to re-render your component after the state changes. Updating the state with proper action (to update username) will cause a re-render in the Topbar component to get the new username from the store.

Does component Rerender When Redux state change?

New! Save questions or answers and organize your favorite content. Learn more.

How do you update component state React?

To update our state, we use this. setState() and pass in an object. This object will get merged with the current state. When the state has been updated, our component re-renders automatically.

Why is React not updating on state change?

State updates in React are asynchronous; when an update is requested, there is no guarantee that the updates will be made immediately. The updater functions enqueue changes to the component state, but React may delay the changes, updating several components in a single pass.


1 Answers

You need to set up your reducer and initial store properly following the Redux documentation.

You're missing a Provider, which will provide your store to your application.

const store = createStore(reducer, applyMiddleware(thunk));

const rootElement = document.getElementById("root");

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  rootElement
);

Now, your store is available to your components.

Your reducer needs an initial state too and you're always supposed to return an updated copy of your state. That said, don't change the state directly, but make a copy, change it, then return that copy.

const initialState = {
  name: ""
};

const reducer = function(state = initialState, action) {
  if (action.type === "name") {
    return { ...state, name: action.payload };
  } else {
    return state;
  }
};

export default reducer;

You might have noticed that I added a middleware to your store, and that's because it's usually the way to go when accessing your current reducer's state in your actions. That said, I installed redux-thunk for that, so in your action, you can have something like this:

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

Now, with your store being provided to your app, your reducer being done and your actions being ready to go, you can connect different components to your reducer.

You use the high order component in react-redux called connect for that. For example, in your Name component, we can connect the name to be displayed to your reducer by mapping your state to the component's props:

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

const mapStateToProps = state => {
  return {
    name: state.name
  };
};

export default connect(mapStateToProps)(Name);

The nice thing here is that you can also leave the first parameter in the connect high order component empty and just pass the second, which would be the dispatch functions. Well, that's what you would do in your App component, you would connect it to the changeName action.

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);

Now, when App dispatches a changeName action, your reducer state will be updated and the other components that are connected to the reducer's state will re-render.

Summary: Try to think of your store as an empty jar of candies. Your jar starts empty, but different actions could change what's inside the jar. On top of that, different people in the house that know where the jar is can go get some candy. Translating to your problem, your app begins with an empty name and you have an action that sets up a name. The components that know where to find that name by being connected to your reducer will know when that name changes and will get the updated name.

The final code can be found here:

Edit vigilant-field-shfj7

like image 167
Elder Patten Ferreira Avatar answered Oct 19 '22 22:10

Elder Patten Ferreira