关键词
store
reducer, dispatch, action
redux
createStore, combineReducers, applyMiddleware
react-redux
Provider, connect
useDipatch, useSelector, useStore
store
- 引入创建仓库方法:
import {createStore} from 'redux';
- 仓库需要参数:reducer
createStore(reducer)
- 创建reducer, reducer是纯函数
reducer有两个参数:state和action
reducer(state = ?, action) {}
多个reducer:combineReducers({reducerA, reducerB...})
纯函数:(如果函数的调用参数相同,则永远返回相同的结果。函数不会产生任何可观察的副作用)
reducer.js
export default reducerA(state = {loading: true, data: []}, action) {
switch(action.type) {
case 'loading_start':
return {
loading: true,
data: []
};
case 'loading_end':
return {
loading: false,
data: action.data
};
default:
return state;
}
}
reducer使用,store创建
import {createStore ,combineReducers, applyMiddleware} from 'redux'
import homeReducer from './reducer'
import thunk from 'redux-thunk'
const reducers =combineReducers({homeReducer})
export default createStore(reducers, applyMiddleware(thunk))
- 修改state数据的唯一方法:dispatch触发action
dispatch来源:
4-1) connect -import {connect} from 'react-redux'
4-2) useDispatch -import {useDipatch} from 'react-redux'
// 4-1
import {connect} from 'react-redux'
export default connect(
state => {
return {}
},
dispatch => {
// do sth with dispatch
return {}
}
)(MyComponent)
// 4-2
import {useDipatch} from 'react-redux'
const dispatch = useDispatch();
// do sth with dispatch
- action是一个对象,必须包含type属性
{type: ‘loading_end’, data: []}
- store仓库的使用:需要一个提供者组件
import {Provider} from 'react-redux'
使用Provider。要放在顶层<App />
外层,如下:
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
- 获取数据并展示:
7-1)不使用store
7-2)使用connect把获取数据的方法提取出来
7-3)使用hooks把获取数据的方法提取出来
获取列表数据🌰
7-1 不使用store展示数据
// 7-1)
import React, {useState, useEffect} from 'react'
import {useParams} from 'react-router-dom'
export default function HomePage {
const {type, page} = useParams();
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
if (loading) {
http.get(`/topics?page=${page}&tab=${type}&limit=10`)
.then(res => {
setData(res.data.data);
setLoading(false);
})
}
}, [loading])
useEffect(() => {
setLoading(true)
}, [type, page])
return <List data={data} loading={loading} />
}
7-2 connect写法
// 7-2) action.js
export default function getData (dispatch,page, type) {
dispatch({
type: "loading_start"
});
http.get(`/topics?page=${page}&tab=${type}&limit=10`).then(res => {
dispatch({
type: "loading_end",
data: res.data.data
});
});
};
// 7-2) HomePage.js
import {useSelector, connect} from 'react-redux'
import getData from '../../store/action'
function HomePage(){
const {type, page} = useParams();
const { getDataFn } = props;
const {data, loading} = useSelector(state => state.homeReducer)
useEffect(() => {
getDataFn(page, type)
}, [type, page])
return <List data={data} loading={loading} />
}
export default connect((state) => {
return state;
}, (dispatch) => {
return {getDataFn: (page, type) => getData(dispatch, page, type)}
})(HomePage)
7-3 hooks写法
// 7-3) action.js
import {useSelector, useDispatch} from 'react-redux'
const useHomeList = function () {
const dispatch = useDispatch();
return function (page, type) {
dispatch({
type: "loading_start"
});
http.get(`/topics?page=${page}&tab=${type}&limit=10`).then(res => {
dispatch({
type: "loading_end",
data: res.data.data
});
});
};
};
export { useHomeList };
// 7-3)HomePage.js
import {useHomeList} from '../../store/action'
export default HomePage(){
const getData = useHomeList();
const dispatch = useDispatch();
const {type, page} = useParams();
const {data, loading} = useSelector(state => state.homeReducer)
useEffect(() => {
getData(dispatch, page, type)
}, [page, type])
return <List data={data} loading={loading} />
}
专栏系列快速链接
1-从零开始学react-认识react&jsx&props&state
2-从零开始学react-深入state,组件通讯,生命周期,受控组件
3-从零开始学react-其他api,初识hook
4-从零开始学react-hooks相关
5-从零开始学react - react-router-dom5
6-从零开始学react - redux相关
7-从零开始学react - 全家桶项目实战