react合集地址:https://www.jianshu.com/nb/38443782
0. 介绍
我们知道,react的数据传递是从上往下的模式,子组件想访问父组件的数据必须通过父组件将属性传递过来。
![](https://img.haomeiwen.com/i18052029/b48ed0a7caa94487.png)
如上图所示,b组件有一个userList数据,通过属性传递b组件的子组件c也可以访问userList。然后b组件的父组件a以及它的兄弟组件d都是没有办法访问userList的。
要解决这个问题,常规的方法是将userList上移到a组件,然后层层传递,如下图所示
![](https://img.haomeiwen.com/i18052029/f8a8718128e4fbb3.png)
不难想象,如果有很多的数据需要在组件之间传递,那么最顶层的父组件,本例中的a组件中的数据会非常的多,造成a组件非常的庞大。
redux就是为了解决这个问题而产生的,它的作用就是将数据中心化。什么意思,就是将数据单独提取出来到一个公共的地方,所有的组件去这个公共的地方去取数据从而达到数据的访问目的。如下图
![](https://img.haomeiwen.com/i18052029/5f694bbaadfd811b.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打开调试台以后能看到如下的信息。
![](https://img.haomeiwen.com/i18052029/753e91c17efa09fd.png)
3. 安装redux开发工具(chrome版本)
-
react代码和工具建立连接
//store
let store = createStore(
counterReducer,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()//增加的部分
);
安装完毕后,运行react项目出现如下效果。需要点击图标才能出来窗口,右击图标可以选择窗口出来的位置
![](https://img.haomeiwen.com/i18052029/a0204b95a5c28ab3.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。
网友评论