一.涉及到的插件
redux 提供createStore和applyMiddleware react-redux 它能让react组件从redux store读取数据 , 并且分发action到store来更新数据 redux-thunk 网络等异步任务不可或缺的中间件
redux-immutable 引入combineReducers,将combineReducers内的reducer也转换成immutable对象,统一数据格式
二.应用结构
|-- src
|-- App.js
|-- index.js
|-- pages
| |-- discover
| | |-- c-pages
| | |-- album
| | | |-- store
| | | |-- actionCreators.js
| | | |-- constants.js
| | | |-- index.js
| | | |-- reducer.js
| | |-- artist
| | | |-- store
| | | |-- actionCreators.js
| | | |-- constants.js
| | | |-- index.js
| | | |-- reducer.js
| | |
| | |-- djradio
| | | |-- store
| | | |-- actionCreators.js
| | | |-- constants.js
| | | |-- index.js
| | | |-- reducer.js
| | |
| | |-- ranking
| | | |-- store
| | | |-- actionCreators.js
| | | |-- constants.js
| | | |-- index.js
| | | |-- reducer.js
| | |
| | |-- recommend
| | | |-- store
| | | |-- actionCreators.js
| | | |-- constants.js
| | | |-- index.js
| | | |-- reducer.js
| | |
| | |-- songs
| | |-- store
| | |-- actionCreators.js
| | |-- constants.js
| | |-- index.js
| | |-- reducer.js
| |-- player
| |-- store
| |-- actionCreators.js
| |-- constants.js
| |-- index.js
| |-- reducer.js
|-- store
| |-- index.js
| |-- reducer.js
三.使用步骤
1.定义入口文件(App.js)
从react-redux引入Provider,Provider 负责将 store 传递给内部所有组件
要将自己的app包含在Provider中 , redux store才会生效。
import React from 'react';
//Provider 负责将 store 传递给内部所有组件
import { Provider } from "react-redux";
//引入定义好的状态管理器
import store from "./store";
//引入自己的app
import HYMain from './pages/main';
function App() {
return (
<Provider store={store}>
<HYMain/>
</Provider>
);
}
export default App;
2.定义store(/src/store)
reducer.js:用于将子模块的reducer合并
index.js: 包装reducer,统一暴露出口
store
|-- index.js
|-- reducer.js
reducer.js
import { combineReducers } from "redux-immutable";
//app使用到的reducer
import { reducer as recommendReducer } from "../pages/discover/c-pages/recommend/store";
import { reducer as playerReducer } from "../pages/player/store";
...
//将combineReducers内的reducer也转换成immutable对象
export default combineReducers({
recommend: recommendReducer,
player: playerReducer,
...
})
index.js
createStore:创建一个 Redux store 来以存放应用中所有的 state。createStore(reducer, [preloadedState], [enhancer])
applyMiddleware :将所有中间件组成一个数组,依次执行。applyMiddleware(...middleware)
thunk:处理网络等异步任务不可或缺的中间件,
compose:从右到左来组合多个函数。compose(...functions)
import { createStore, compose, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import reducer from './reducer';
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducer, composeEnhancers(
applyMiddleware(thunk)
));
export default store;
3.定义模块的store
actionCreators:action的统一管理文件
constants:常量管理文件,用于声明事件名称
reducer:事件触发器
index:store入口
|-- player
|-- store
|-- actionCreators.js
|-- constants.js
|-- index.js
|-- reducer.js
actionCreators.js
当前项目的action分为两类
第一种:偏向无业务逻辑,只对返回actionType和入参,也就是只对state做赋值操作
第二类:偏向业务逻辑,可以做逻辑判断,接口调用等等。调用第一种ation来间接操作state
import * as actionTypes from './constants';
//第一类
export const demoAction = (params) => ({
type: actionTypes.DEMO,
params
})
//第二类
export const xxxAction = () => {
//返回函数的入参(dispatch, getState)
//dispatch用于派发action事件,getState用于获取state里的值
return (dispatch, getState) => {
const id=getState().getIn(["moduleA","demoId"])
getById(id).then(res=>{
dispatch(demoAction(res));
})
}
}
示例代码
const changeSimiSongsAction = (res) => ({
type: actionTypes.CHANGE_SIMI_SONGS,
simiSongs: res.songs
})
export const getSimiSongAction = () => {
return (dispatch, getState) => {
const id = getState().getIn(["player", "currentSong"]).id;
if (!id) return;
getSimiSong(id).then(res => {
dispatch(changeSimiSongsAction(res));
})
}
}
constants.js
一般用于定义派发事件的type
export const CHANGE_SIMI_PLAYLIST = "player/CHANGE_SIMI_PLAYLIST";
export const CHANGE_SIMI_SONGS = "player/CHANGE_SIMI_SONGS";
reducer.js
//用于存储state的数据结构
import { Map } from 'immutable';
import * as actionTypes from './constants';
//state
const defaultState = Map({
playList:[],
simiSongs:[]
})
//定义reducer,用于接收派发事件
function reducer(state = defaultState, action) {
switch (action.type) {
case actionTypes.CHANGE_SIMI_PLAYLIST:
return state.set("simiPlaylist", action.simiPlaylist);
case actionTypes.CHANGE_SIMI_SONGS:
return state.set("simiSongs", action.simiSongs);
default:
return state;
}
}
export default reducer;
4.在模块中使用
useSelector:可以连接redux,获取其state。(第二个入参为其更新依赖)
shallowEqual:浅层对比,一般搭配useSelector使用,作为其第二个入参。
useDispatch:执行得到dispatch方法
import { useSelector, shallowEqual, useDispatch } from 'react-redux';
import { useEffect } from 'react';
const {
currentSong,
playList,
} = useSelector(state => ({
currentSong: state.getIn(["player", "currentSong"]),
playList: state.getIn(["player", "playList"]),
}), shallowEqual);
//获取dispatch方法
const dispatch = useDispatch();
//更新依赖项为dispatch,当useDispatch()执行之后,useEffect函数会被更新
useEffect(() => {
dispatch(getSongDetailAction(167876));
}, [dispatch]);