通过redux更改状态后如何更新React组件? [英] How to update React component after changing state through redux?

查看:229
本文介绍了通过redux更改状态后如何更新React组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 React 和 Redux,同时我决定制作带有按钮的网页,点击该按钮会改变状态.在按钮下方,我想在不同的组件中显示当前状态.虽然点击按钮改变了状态,但它并没有反映在组件中.这是我的代码:

App.js

从 'react' 导入 React从'./Name'导入名称从 './Action' 导入 {changeName};导出默认函数 App() {返回 (<div><button onClick={changeName}>点击我</button><姓名/>

)}

名称.js

从 'react' 导入 React从 './Store' 导入 {store}函数名称(道具){返回 (<div>我的名字是:{store.getState()}

)}导出默认名称

Store.js

import { createStore } from 'redux';从'./Reducer'导入{reducer};export const store = createStore(reducer, 'Tarun');

Action.js

import {store} from './Store';export const changeName = () =>{if (store.getState() === "塔伦"){store.dispatch({ type: 'name', payload: 'Subhash' });}别的{store.dispatch({ type: 'name', payload: 'Tarun' });}}

Reducer.js

export const reducer = function(state, action) {if (action.type === 'name') {返回 action.payload;}返回状态;};

当我单击按钮时,Name 组件内的文本不会改变.有什么问题?

解决方案

您需要按照 Redux 文档正确设置减速器和初始存储.

您缺少一个 Provider,它将为您的应用程序提供您的 store.

const store = createStore(reducer, applyMiddleware(thunk));const rootElement = document.getElementById("root");ReactDOM.render(<提供者商店={商店}><应用程序/></提供者>,根元素);

现在,您的商店可用于您的组件.

您的 reducer 也需要一个初始状态,并且您总是应该返回状态的更新副本.也就是说,不要直接更改状态,而是创建一个副本,更改它,然后返回该副本.

const initialState = {名称: ""};const reducer = function(state = initialState, action) {if (action.type === "name") {返回 { ...状态,名称:action.payload };} 别的 {返回状态;}};导出默认减速器;

您可能已经注意到,我在您的商店中添加了一个中间件,这是因为在您的操作中访问当前减速器的状态时通常会采用这种方式.也就是说,我为此安装了 redux-thunk,所以在你的操作中,你可以有这样的东西:

export const changeName = () =>{返回(调度,getState)=>{if (getState().name === "Tarun") {dispatch({ type: "name", payload: "Subhash" });} 别的 {dispatch({ type: "name", payload: "Tarun" });}};};

现在,您的商店已提供给您的应用,您的减速器已完成并且您的操作已准备就绪,您可以将不同的组件连接到减速器.

您为此使用了 react-redux 中名为 connect 的高阶组件.例如,在您的 Name 组件中,我们可以通过将您的状态映射到组件的 props 来将要显示的名称连接到您的 reducer:

函数名称(道具){return <div>我的名字是:{props.name}</div>;}const mapStateToProps = state =>{返回 {名称:state.name};};导出默认连接(mapStateToProps)(名称);

这里的好处是,您还可以将 connect 高阶组件中的第一个参数留空,然后只传递第二个参数,即调度函数.嗯,这就是您在 App 组件中要做的事情,您将它连接到 changeName 操作.

function App(props) {返回 (<div><button onClick={props.changeName}>点击我</button><姓名/>

);}const mapDispatchToProps = dispatch =>{返回 {更改名称:() =>调度(更改名称())};};导出默认连接(空值,mapDispatchToProps)(应用程序);

现在,当 App 分派 changeName 操作时,您的减速器状态将被更新,并且连接到减速器状态的其他组件将重新渲染.

总结:试着把你的商店想象成一罐空糖果.你的罐子开始是空的,但不同的动作可能会改变罐子里的东西.最重要的是,房子里知道罐子在哪里的不同人可以去拿一些糖果.转化为您的问题,您的应用程序以一个空名称开头,并且您有一个设置名称的操作.通过连接到您的reducer知道在哪里可以找到该名称的组件将知道该名称何时更改并获得更新的名称.

最终代码可以在这里找到:

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?

解决方案

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:

这篇关于通过redux更改状态后如何更新React组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆