首页 > 解决方案 > 在 React 项目中添加 Redux

问题描述

在 React 项目中添加 redux(用 Redux 重构一个简单的项目)

考虑一个简单的项目,一个使用两个按钮的计数器应用程序,一个用于递增,另一个用于递减计数器值。

在实际场景中,我们使用状态来保存计数器值,如下所示:

App.js中:

import React, {Component} from 'react';
import CounterApp from './CounterApp'

class App extends Component {
  render() {
    return (
      <CounterApp/>
    );
  }
}

export default App;

CounterApp.js中:

import React, {Component} from 'react';

class CounterApp extends Component {
  state = {
    counter: 0
  };

  handleIncrement = () => {
    this.setState(prevState => ({
      counter: prevState.counter + 1
    }))
  };

  handleDecrement = () => {
    this.setState(prevState => ({
      counter: prevState.counter - 1
    }))
  };

  render() {
    return (
      <div>
        <button onClick={this.handleIncrement}>Increment</button>
        <p>{this.state.counter}</p>
        <button onClick={this.handleDecrement}>Decrement</button>
      </div>
    );
  }
}

export default CounterApp;

一个简单而基本的示例,它使用 react 类组件实现并由两个函数处理程序 (handleIncrementhandleDecrement)处理

一个state有值的,counter

我正在使用prevState,因为当您被迫使用时,这是最佳this.state.实践setState

现在,这个Redux的实现会是什么?

标签: javascriptreactjsreact-nativeredux

解决方案


首先,您需要通过或将reduxreact-redux包安装到您的项目中。npmyarn

您可以使用一行代码简单地安装它们:

npm install redux react-redux --save

或用纱线:

yarn add redux react-redux

现在回到项目并使用以下名称创建 3 个文件:

action.js,reducer.jsstore.js

打开action.js文件。我们应该为这个应用程序实现两个动作。一个用于递增,一个用于递减。

action.js中

const INCREMENT_COUNTER = 'INCREMENT_COUNTER';
const DECREMENT_COUNTER = 'DECREMENT_COUNTER';

const increment = () => ({type: INCREMENT_COUNTER});
const decrement = () => ({type: DECREMENT_COUNTER});

export {
  INCREMENT_COUNTER,
  DECREMENT_COUNTER,
  increment,
  decrement
}

动作是从组件分派到 redux 的简单函数,用于store通过 reducer 更改(状态)。

所以我们应该改变reducer.js

import {INCREMENT_COUNTER, DECREMENT_COUNTER} from "./action";

const initialState = {
  counter: 0
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case(INCREMENT_COUNTER):
      return {
        ...state,
        counter: state.counter + 1
      };
    case (DECREMENT_COUNTER):
      return {
        ...state,
        counter: state.counter - 1
      };
    default:
      return state
  }
};

export default reducer

使用 redux 有 3 个主要原则:

1-单一事实来源。整个应用程序的状态存储在单个存储中的对象树中。

2- 状态是只读的。改变状态的唯一方法是发出一个动作,一个描述发生了什么的对象。

3- 使用纯函数进行更改。

根据第二个原则,我们必须假设状态是不可变的,并且每个 case(in switch) 必须单独返回状态。在返回的状态中使用 ...state 意味着如果 initialState 将来会发生变化,这些情况将正常工作(在此示例中没有必要)。

我们在行动中的功能是纯粹的(第三条原则)

最后一个新文件store.js

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

const store = createStore(reducer);

export default store;

现在我们应该将此商店应用到我们的 App 组件。所以打开 App.js 文件并进行以下更改:

App.js中:

import React, {Component} from 'react';
import CounterApp from './CounterApp'
import {Provider} from 'react-redux'
import store from './store'

class App extends Component {
  render() {
    return (
      <Provider store={store}>
        <CounterApp/>
      </Provider>
    );
  }
}

export default App;

Provider 包装了CounterApp组件并将传播storeAppCounterApp所有其他子组件。

最后,更改CounterApp.js

import React, {Component} from 'react';
import {connect} from "react-redux";
import {increment, decrement} from "./action";

class CounterApp extends Component {

  handleIncrement = () => this.props.dispatch(increment());

  handleDecrement = () => this.props.dispatch(decrement());

  render() {
    return (
      <div>
        <button onClick={this.handleIncrement}>Increment</button>
        <p>{this.props.counter}</p>
        <button onClick={this.handleDecrement}>Decrement</button>
      </div>
    );
  }
}

const mapStateToProps = state => {
  const counter = state.counter;
  return {counter}
};

export default connect(mapStateToProps)(CounterApp);

我们正在使用increment&decrement动作将动作分派给 redux。

被移除了state,我们创建了一个特殊的函数mapStateToProps' and useconnect 来代替 state 来将 state 连接到组件 props。

完成了!


推荐阅读