沃梦达 / IT编程 / 前端开发 / 正文

在 React 中使用 Redux 解决的问题小结

在React中使用Redux可以解决以下问题:

在React中使用Redux可以解决以下问题:

  1. 多个组件需要共享的状态管理
  2. 需要管理复杂的组件状态
  3. 状态需要可以被时间旅行(Time Travel)调试

以下是使用Redux的完整攻略:

安装 Redux

首先需要在项目中安装Redux,可以使用npm或者yarn。示例命令如下:

npm install redux
yarn add redux

创建 Redux Store

一旦安装了Redux,接下来需要通过创建一个Redux Store来存储应用程序的状态。Redux Store是一个只读状态的树结构,存储应用程序的所有状态。可以使用Redux中提供的 createStore 函数来创建。

创建Redux Store的示例代码:

import { createStore } from 'redux';

const initialState = { counter: 0 };

function reducer(state = initialState, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { counter: state.counter + 1 };
    case 'DECREMENT':
      return { counter: state.counter - 1 };
    default:
      return state;
  }
}

const store = createStore(reducer);

在这个示例中,我们创建了一个初始状态为 { counter: 0 } 的Redux Store,并传入了一个 reducer 函数。

创建 Redux Reducer

Reducers是函数,负责处理并返回新的状态。每个Reducer都处理State的一部分。Reduce函数接收两个参数:state和action。State是当前状态的快照,而action包含派生状态的数据。

有多个Reducer的store把State树分解成若干部分,并对每个部分进行书写:

function todos(state = [], action) {
  switch (action.type) {
    case ADD_TODO:
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    case TOGGLE_TODO:
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: !todo.completed
          })
        }
        return todo
      })
    default:
      return state
  }
}

function visibilityFilter(state = SHOW_ALL, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return action.filter
    default:
      return state
  }
}

function todoApp(state = {}, action) {
  return {
    todos: todos(state.todos, action),
    visibilityFilter: visibilityFilter(state.visibilityFilter, action)
  }
}

let store = createStore(todoApp)

在这个示例中,我们创建了一个 todos 和一个 visibilityFilter reducer。Redux Store的初始状态是由 todoApp reducer 中的默认值决定的。

使用 Redux Provider

Redux提供了一个 Provider 组件,用于将Redux Store连接到React组件树中。我们需要在根组件中使用Provider并传入Redux Store,这样所有的子组件都可以通过访问该Store来获取状态。

示例代码:

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

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);

在这个示例中,我们在根组件中使用React-Redux的 Provider 组件,设置 store 属性,从而让整个React组件树都可访问 store

在组件中访问 Redux 状态

通过React-Redux提供的 connect 函数,我们可以连接React组件与Redux Store。将状态作为组件的props传递给组件,从而让组件访问Redux Store。

示例代码:

import { connect } from 'react-redux';

function Counter({ counter, dispatch }) {
  return (
    <div>
      <h1>Counter</h1>
      <p>Counter value: {counter}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
    </div>
  );
}

const mapStateToProps = state => ({
  counter: state.counter,
});

export default connect(mapStateToProps)(Counter);

在这个示例中,我们使用 connect 函数将组件与Redux Store连接起来。我们使用 mapStateToProps 函数来传递 counter 这个状态。

通过这些步骤,我们就成功使用React和Redux来解决组件状态管理的问题。下面是其他一些示例。

示例一:使用 Redux 来存储共有的用户名

Reducers实现:

const initialState = {
  username: '',
  ...
}

const SET_USERNAME = 'SET_USERNAME';

function rootReducer(state = initialState, action) {
  switch (action.type) {
    case SET_USERNAME:
      return { ...state, username: action.payload };
    default:
      return state;
  }
}

Login 组件:

function Login(props) {
  const [inputText, setInputText] = useState('');

  const handleSubmit = e => {
    e.preventDefault();
    props.setUsername(inputText);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="text" value={inputText} onChange={(e) => setInputText(e.target.value)} />
      <button type="submit">Submit</button>
    </form>
  );
}

const mapDispatchToProps = {
  setUsername: (username) => ({ type: SET_USERNAME, payload: username })
};

export default connect(null, mapDispatchToProps)(Login);

App 组件(如何获取并使用用户名):

function App(props) {
  const { username } = props;

  return (
    <>
      <h1>Welcome, {username}!</h1>
      // 其他模块的逻辑
    </>
  );
}

const mapStateToProps = state => ({
  username: state.username,
})

export default connect(mapStateToProps)(App);

示例二:使用Redux管理弹出窗口状态

Reducers实现:

const initialState = { showModal: false };

const SHOW_MODAL = 'SHOW_MODAL';

function rootReducer(state = initialState, action) {
  switch (action.type) {
    case SHOW_MODAL:
      return { ...state, showModal: !state.showModal };
    default:
      return state;
  }
}

App 组件:

import { useState } from 'react';
import Modal from './Modal';
import { connect } from 'react-redux';

function App(props) {
  const { showModal, toggleModalVisibility } = props;
  const [text, setText] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    setText('');
    toggleModalVisibility();
  };

  const handleInputChange = (e) => {
    setText(e.target.value);
  };

  return (
    <>
      <button onClick={toggleModalVisibility}>Toggle Modal</button>
      <Modal show={showModal}>
        <form onSubmit={handleSubmit}>
          <input type="text" value={text} onChange={handleInputChange} />
          <button type="submit">Submit</button>
        </form>
      </Modal>
    </>
  );
}

const mapStateToProps = (state) => ({
  showModal: state.showModal,
});

const mapDispatchToProps = {
  toggleModalVisibility: () => ({ type: SHOW_MODAL }),
};

export default connect(mapStateToProps, mapDispatchToProps)(App);

使用这个方法可以管理更为复杂、需要共享的状态。

本文标题为:在 React 中使用 Redux 解决的问题小结