Redux
Redux的使用
import {createStore} from 'redux';
const store = createStore((state={count:1,name:'xiaoming'},action)=>{
switch(action.type){
case 'ADD':
return {
...state,
count:state.count+1
}
case 'MINS':
return {
...state,
count:state.count-1
}
default:
return {
...state,
count:state.count
}
}
})
export default store;
createStore中传入reducer,reducer是一个函数,有两个参数state和action,通过判断action的判断来对state执行不同的操作;
Redux api
createStore(reducer, [preloadedState], enhancer);
- reducer (Function): 接收两个参数,分别是当前的 state 树和要处理的 action,返回新的 state 树。
- [preloadedState] (any): 初始时的 state。 在同构应用中,你可以决定是否把服务端传来的 state 后传给它,或者从之前保存的用户会话中恢复一个传给它。如果你使用 combineReducers 创建 reducer,它必须是一个普通对象,与传入的 keys 保持同样的结构。否则,你可以自由传入任何 reducer 可理解的内容。
- enhancer (Function): Store enhancer 是一个组合 store creator 的高阶函数,返回一个新的强化过的 store creator。这与 middleware 相似,它也允许你通过复合函数改变 store 接口。
- 返回值 (Store): 保存了应用所有 state 的对象。改变 state 的惟一方法是 dispatch action。你也可以 subscribe 监听 state 的变化,然后更新 UI。
reducer
- reducer(state,action)
Store
- getState()
- dispatch(action):dispatch传入action对象,触发reducer;
- subscribe(listener):subscribe用来监控state的变化,返回的参数用来取消监控;
- replaceReducer(nextReducer):replaceReducer替换reducer;
combineReducers(reducers)
将 reducer 函数拆分成多个单独的函数,拆分后的每个函数负责独立管理 state 的一部分
applyMiddleware(...middlewares) 中间件
Redux三大原则
-
单一数据源:整个应用的 state 被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个 store 中
-
state是只读的:唯一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象
-
使用纯函数来执行修改
高阶函数和纯函数
reducer的拆分与合并
使用combineReducers合并reducer
import { createStore, combineReducers} from "redux";
/*
reducer 的拆分与合并:
action.type 在项目中时唯一的
*/
//reducer的拆分
const count = (count=1,action)=>{
switch (action.type) {
case "COUNT_ADD":
return count + 1;
case "COUNT_MINS":
return count - 1;
default:
return count;
}
}
const list = (list={
type: "all",
data: [],
nub: 1
},action)=>{
switch (action.type) {
case "LIST_ADD":
return {
...list,
nub: list.nub + 1
}
case "LIST_MINS":
return {
...list,
nub: list.nub - 1
};
default:
return list;
}
}
// reducer 的合并
// const reducer = (state = {
// count: 1,
// list: {}
// }, action) => {
// return {
// count:count(state.count,action),
// list: list(state.list,action)
// }
// }
// reducer 的合并
const reducer = combineReducers({
count,
list
});
const store = createStore(reducer);
export default store;
React-redux
状态绑定
将仓库(store)通过Provider组件传给App
import ReactDOM from 'react-dom';
import App from './App';
import { Provider } from 'react-redux';
import store from './store';
ReactDOM.render(
<Provider store={store}>
<App></App>
</Provider>,
document.querySelector("#root")
);
接收参数
- connect
const withConnect = connect((state) => {
const {count} = state;
return {count};//返回值是state中要传递给组件的数据,必须是一个对象!
})
//App传下来的props通过withConnect会自动组合到state中传给App组件
export default withConnect(App);
- hooks
-
useDispatch获取dispatch
-
useStore获取store
-
useSelector获取state
import { useDispatch, useSelector, useStore } from "react-redux"
function App(props) {
const dispatch = useDispatch();
const count = useSelector(state=>state.count);
const store = useStore();
console.log(store.getState());
console.log(props);
return <div>
<p>{count}</p>
<button onClick={() => {
dispatch({ type: 'ADD' })
}}>+</button>
<button onClick={() => {
dispatch({
type: 'MINS'
})
}}>-</button>
</div>
}
export default App;
redux-thunk
ps:不是react-thunk !!!
使用
使用 thunk 中间件后,action可以支持两种形式: "函数" 和 "对象"
- 参数是对象,直接调用 reducer 修改我们的 state
- ,参数是函数调用该函数,并且把 dispatch 和 getState 传递我们的函数,可以在函数中,进行异步操作
import { createStore, applyMiddleware} from "redux";
import thunk from "redux-thunk";
const reducer = <你的reducer>
const store = createStore(reducer,applyMiddleware(thunk));
异步获取数据问题
举例:根据不同的type获取cnode( cnodejs.org/api )的list数据
store.js
import { createStore, combineReducers, applyMiddleware} from "redux";
import thunk from "redux-thunk";
const list = (list={
type: "all",
data: [],
loading: true
},action)=>{
switch (action.type) {
case "LIST_LOADING":
return {
...list,
data: [],
loading: true
}
case "LIST_LOAD":
return {
...list,
data: action.data,
loading: false
}
case "LIST_TYPECHANGE":
return {
...list,
type: action.dataType,
}
default:
return list;
}
}
const reducer = combineReducers({
list
});
const store = createStore(reducer,applyMiddleware(thunk));
export default store;
app.js
import { useEffect } from "react";
import { useSelector,useDispatch } from "react-redux";
import { getListData } from "./actions";
// ask share job good
function App() {
const list = useSelector(state => state.list);
const {type,data,loading} = list;
const dispatch = useDispatch();
useEffect(()=>{
dispatch(getListData);
},[type]);
return <div>
<button onClick={()=>{
dispatch({
type: "LIST_TYPECHANGE",
dataType: "all"
})
}}>all</button>
<button onClick={()=>{
dispatch({
type: "LIST_TYPECHANGE",
dataType: "ask"
})
}}>ask</button>
<button onClick={()=>{
dispatch({
type: "LIST_TYPECHANGE",
dataType: "share"
})
}}>share</button>
{loading?<div>数据更新中</div>:<ul>{
data.map(item=><li key={item.id}>{item.title}</li>)
}</ul>}
</div>
}
export default App;
import axios from "axios";
function getListData(dispatch, getState) {
dispatch({
type: "LIST_LOADING"
});
axios.get(`https://cnodejs.org/api/v1/topics?page=1&tab=${getState().list.type}&limit=10`).then(res => {
dispatch({
type: "LIST_LOAD",
data:res.data.data
})
})
}
export { getListData };
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!