React 状态——Redux(上)

1,069 阅读3分钟

一、概念

一个可预测的 JavaScript 应用状态管理容器(容器即为Store)。

  • View:视图层,即React;
  • Store:保持状态,分发状态给 View,使得 View 根据这些状态渲染不同的内容。
  • Reducers:响应不同的动作,负责更新 Store 中状态的 JavaScript 函数。

二、项目引用

// 安装依赖
npm install redux
npm install react-redux

三、Store: 数据的唯一真相来源

1、React 状态 “危机”

在 React 中,状态存在每个组件的 this.state 中,每个组件的 state 为组件所私有,如果要在一个组件中操作另外一个组件,实现起来是相当繁琐的。

如上图,不仅要把 handleClick 方法通过很深的层级传给组件 B,当组件 B 调用 handleClick 方法时,修改组件 A 的 state,再反过来传递给组件 C 时,组件 A 到组件 C 之间的所有组件都会触发重新渲染,这带来了巨额的渲染开销。

2、解救者:Store

思路:抽离所有组件的状态,类比 React 组件树,用js对象来构造一个中心化的状态树,相当于对 React 组件树进行了状态化建模。

如下图,组件 B 中发起一个更新状态 C 的动作,此动作对应的更新函数更新 Store 状态树,之后将更新后的状态 C 传递给组件 C,触发组件 C 的重新渲染。

四、理解 Action: 改变 State 的唯一手段

更新 Store 状态唯一方式:调用 dispatch 函数,传递一个 action(简单的 JavaScript 对象) 给这个函数 。

dispatch({ type: 'ADD_TODO', text: '我是一只小小小图雀' , id: 0})

为了简化Action的写法,可定义函数并传入需要变化的参数即可,这个函数被称为Action Creators(动作创建器):

// Action Creators
let nextTodoId = 0;

const addTodo = text => ({
  type: "ADD_TODO",
  id: nextTodoId++,
  text
});

// dispatch
dispatch(addTodo('我是一只小小小图雀'))

五、理解 Reducers: 响应 Action 的指令

Reducers:响应从组件中 dispatch 出来 Action,并更新 Store 中的状态;

1、纯化的 Reducers

reducer 是一个普通的 JavaScript 函数,它接收两个参数:state 和 action

  • state: Store 中存储的那棵 JavaScript 对象状态树
  • action:组件中 dispatch 的 Action

reducer 根据 action 的指示,对 state 进行对应的操作,然后返回操作后的 state,Redux Store 会自动保存这份新的 state。

reducer(state, action) {
  // 对 state 进行操作
  return newState;
}

2、纯化

  • 定义:不直接修改原对象,而是返回一个新对象的修改;
  • 例子: 对 state = { a: 1, b: 2 } 进行修改,将 a 替换成 3,应该是:newState = { ...state, a: 3 },而不是 state.a = 3。

六、Redux 上的函数

  • dispatch(action): 用来在 React 组件中发出修改 Store 中保存状态的指令。
  • reducer(state, action): 用来根据这一指令修改 Store 中保存状态对应的部分。
  • connect(mapStateToProps) :用来将更新好的数据传给组件,然后触发 React 重新渲染,显示最新的状态。它架设起 Redux 和 React 之间的数据通信桥梁。

七、Redux 的项目实践

  • 1、在入口文件中,创建store并利用Provider将store下发给组件
// index.js
import { createStore } from "redux";// 从 redux 中导出了 createStore
import { Provider } from "react-redux";// 从 react-redux 导出了 Provider

// 创建初始状态数据
const initialState = {}

// reducer
const rootReducer = (state, action) => {}

// 生成store
const store = createStore(rootReducer, initialState);

  ReactDOM.render(
    <Provider store={store}>
      <App />
    </Provider>,
    document.getElementById("root")
  );
  • 2、在主组件中
// App.js
import { connect } from "react-redux";

class App extends React.Component {
  render() {
  	const {} = this.props// 通过props获取store
     	return {
      		dispatch(ACTION);// 发出修改
  	}
}
// mapStateToProps同时操作组件的原 props 和 Store 的状态,然后合并成最终的组件 props
const mapStateToProps = (state, props) => ({
  todos: state.todos,
  filter: state.filter
});
  
// 获取 mapStateProps 返回的最终组合后的状态,然后将其注入到 App 组件中,返回一个新的组件
export default connect(mapStateToProps)(App);

  • 3、在子组件中,无需合并props
// AddTodo.js
import { connect } from "react-redux";

const AddTodo = ({ dispatch  }) => {
  return (
    <div dispatch(ACTION)>点击触发</div>
  );
};

// 获取 mapStateProps 返回的最终组合后的状态,然后将其注入到 App 组件中,返回一个新的组件
export default connect()(AddTodo);