美文网首页让前端飞Web前端之路
react-(7)使用redux来统一管理数据

react-(7)使用redux来统一管理数据

作者: bugWriter_y | 来源:发表于2019-07-07 21:21 被阅读4次

react合集地址:https://www.jianshu.com/nb/38443782

0. 介绍

我们知道,react的数据传递是从上往下的模式,子组件想访问父组件的数据必须通过父组件将属性传递过来。

Snipaste_2019-07-07_21-19-11.png

如上图所示,b组件有一个userList数据,通过属性传递b组件的子组件c也可以访问userList。然后b组件的父组件a以及它的兄弟组件d都是没有办法访问userList的。

要解决这个问题,常规的方法是将userList上移到a组件,然后层层传递,如下图所示

Snipaste_2019-07-07_21-19-18.png

不难想象,如果有很多的数据需要在组件之间传递,那么最顶层的父组件,本例中的a组件中的数据会非常的多,造成a组件非常的庞大。

redux就是为了解决这个问题而产生的,它的作用就是将数据中心化。什么意思,就是将数据单独提取出来到一个公共的地方,所有的组件去这个公共的地方去取数据从而达到数据的访问目的。如下图

Snipaste_2019-07-07_21-19-27.png

那么具体在react中怎么使用redux呢。IT'S CODING TIME

1. 安装redux

npm install redux react-redux

包括redux本身,以及react与redux的关联包react-redux

2. 使用redux

此处只是介绍redux的使用,还没有和react联系起来,可以看到我们只导入了redux包下的createStore方法

import React from "react";
import ReactDOM from "react-dom";
import * as serviceWorker from "./serviceWorker";
import "bootstrap/dist/css/bootstrap.min.css";
import App from "./App";
import { createStore } from "redux";

//action
const increment = () => {
  return {
    type: "INCREMENT"
  };
};
const decrement = () => {
  return {
    type: "DECREMENT"
  };
};
//reducer
const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default :
      return state;
  }
};
//store
let store = createStore(counterReducer);

//dispatcher
console.log(store.getState());
store.dispatch(increment());
console.log(store.getState());
store.dispatch(decrement());
console.log(store.getState());
store.dispatch(decrement());
console.log(store.getState());

ReactDOM.render(<App />, document.getElementById("root"));
serviceWorker.unregister();

redux的4个关键概念

  • action

可以理解为是一个信号,每一个信号都有一个type。可以包含数据,下面会将

  • reducer

可以理解为是数据以及根据信号进行数据的变化。我们通过代码可以看到,reducer将信号和数据联系在了一起

  • store

可以理解为是存储数据的一个公共的地方。我们通过createStore方法将reducer数据变成了一个store

  • dispatch

可以理解为触发信号的一个动作。触发了信号后,reducer可以根据信号进行数据变化。

这个的例子我们是手动触发了一个增加的信号和两个减少的信号。因此f12打开调试台以后能看到如下的信息。

Snipaste_2019-07-07_20-33-12.png

3. 安装redux开发工具(chrome版本)

//store
let store = createStore(
  counterReducer,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()//增加的部分
);

安装完毕后,运行react项目出现如下效果。需要点击图标才能出来窗口,右击图标可以选择窗口出来的位置

Snipaste_2019-07-07_20-04-09.png

4. react项目中使用redux

  • 因为可能会有很多action和reducer,所以将action和reducer移动到单独的文件和目录中。

src/actions/index.js

创建并导出了两个action,这里和上面有了一点儿区别,我们增加了参数,表示增加多少值。之前我们是写死只增加1,这里我们可以动态传递参数来实现每一次增加减少值的大小。

export const increment = num => {
  return {
    type: "INCREMENT",
    data: num
  };
};
export const decrement = num => {
  return {
    type: "DECREMENT",
    data: num
  };
};

src/reducers/counterReducer

const counterReducer = (state = 0, action) => {
  switch (action.type) {
    case "INCREMENT":
      return state + action.data;
    case "DECREMENT":
      return state - action.data;
    default:
      return state;
  }
};
export default counterReducer;

src/reducers/isLoggedReducer

const isLoggedReducer = (state = false, action) => {
  switch (action.type) {
    case "SIGNIN":
      return true;
    default:
      return state;
  }
};
export default isLoggedReducer;

src/reducers/index.js

因为上面创建了多个reducer,我们通过一个公共的文件index.js将他们整合成一个reducer。这里我们还分别给reducer起了一个名字(分别是counter和isLogged)。

import { combineReducers } from "redux";
import counterReducer from "./counterReducer";
import isLoggedReducer from "./isLoggedReducer";

const allReducers = combineReducers({
  counter: counterReducer,
  isLogged: isLoggedReducer
});
export default allReducers;
  • 将根组件使用redux的provider包围起来,这样其他组件才能访问redux

src/index.js

import React from "react";
import ReactDOM from "react-dom";
import * as serviceWorker from "./serviceWorker";
import "bootstrap/dist/css/bootstrap.min.css";
import App from "./App";
import { createStore } from "redux";
import allReducers from "./reducers";
import { Provider } from "react-redux";//导入Provider组件

//store
let store = createStore(
  allReducers,
  window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
);

ReactDOM.render(
  <Provider store={store}>//使用Provider组件将原本的根组件App包围起来
    <App />
  </Provider>,
  document.getElementById("root")
);
serviceWorker.unregister();

  • 在需要访问数据的组件通过redux访问数据

src/App.js

import React from "react";
import { useSelector, useDispatch } from "react-redux";//导入useSelector和useDispatch
import { increment, decrement } from "./actions";//导入用到的信号
function App() {
  const counter = useSelector(state => state.counter);//通过useSelector从redux中取出名字是counter的数据(这个名字是在allReducer中起的别名)
  const isLogged = useSelector(state => state.isLogged);//通过useSelector从redux中取出名字是islogged的数据(这个名字是在allReducer中起的别名)
  const dispatch = useDispatch();//通过useDispath()从redux中取出能触发信号的方法
  return (
    <div>
      <h1>Count:{counter}</h1>
      <button onClick={() => dispatch(increment(5))}>+</button>
      <button onClick={() => dispatch(decrement(2))}>-</button>
      {isLogged === true ? <p>欢迎登陆</p> : <p>请登录</p>}
    </div>
  );
}
export default App;

点击+,触发increment(5)信号,increment信号的type是"INCREMENT",从reducers中的配置可以知道INCREMENT信号能将counter数据增加,增加的值是increment信号传递过来的数据,此处传递的是5,所以是增加5。

相关文章

网友评论

    本文标题:react-(7)使用redux来统一管理数据

    本文链接:https://www.haomeiwen.com/subject/xewihctx.html