Redux使用
Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
1. 安装redux
安装redux
npm install --save redux
多数情况下,你还需要使用 React 绑定库和开发者工具。
npm install --save react-redux
npm install --save-dev redux-devtools
react原理图
2. redux示例
redux目录结构(react-redux-demo示例)
|-- .gitignore
|-- package.json
|-- README.md
|-- yarn.lock
|-- public
| |-- favicon.ico
| |-- index.html
| |-- logo192.png
| |-- logo512.png
| |-- manifest.json
| |-- robots.txt
|-- src
|-- App.css
|-- App.js
|-- index.css
|-- index.js
|-- logo.svg
|-- reportWebVitals.js
|-- setupTests.js
|-- components
| |-- Count.jsx
| |-- Products.jsx
|-- redux
|-- store.js
|-- actions
| |-- count.js
| |-- products.js
|-- reducers
|-- count.js
|-- index.js
|-- products.js
2.1 index.js引入redux
使用Provider store={store}外层包裹App
src/index.js
import { Provider } from 'react-redux';
import store from './redux/store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
2.2 定义store
src/redux/store.js
import { createStore, applyMiddleware } from 'redux';
import { combineReducers } from 'redux';
import rootReducer from './reducers';
import thunk from 'redux-thunk'
import { composeWithDevTools } from 'redux-devtools-extension';
export default createStore(combineReducers(rootReducer),
composeWithDevTools(applyMiddleware(thunk)))
2.3 定义actions
分别定义了两个action,productsAction,countAction,然后进行合并
定义countAction
src/actions/count.js
export const INCREMENT = 'INCREMENT COUNT';
export const increment = data => ({ type: INCREMENT, data })
export const incrementAsync = data => dispatch => {
setTimeout(() => {
dispatch(increment(data))
}, 2000)
}
定义productsAction
src/actions/products.js
export const ADD_PRODUCT = 'ADD PRODUCT';
export function addProduct(data) {
return {
type: ADD_PRODUCT,
data
}
}
2.4 定义Reducer
定义rootReducer
src/reducers/index.js
分别定义了两个Reducer,productsReducer,countReducer,然后进行合并
import productsReducer from './products';
import countReducer from './count';
const rootReducer = {
products: productsReducer,
count: countReducer
}
export default rootReducer;
定义productsReducer
src/reducers/products.js
import { ADD_PRODUCT } from '../actions/products';
const initState = [];
const productsReducer = (state = initState, action) => {
const { data, type } = action;
switch (type) {
case ADD_PRODUCT:
return [data, ...state];
default:
return state;
}
}
export default productsReducer;
定义countReducer
src/reducers/countReducer.js
import { INCREMENT } from '../actions/count';
const initState = 0;
const countReducer = (state = initState, action) => {
const { data, type } = action;
switch (type) {
case INCREMENT:
return state + data;
default:
return state;
}
}
export default countReducer;
目前reducer与actions已经定义完毕
2.5 组件中使用redux
使用connect连接react-redux与组件
import { connect } from "react-redux";
/*
connect柯里化函数:
一阶参数中传入(mapStateToProps,mapDispatchToProps)
mapStateToProps映射store中的state到组件的props
*/
connect(mapStateToProps, mapDispatchToProps)(Count)
/*
通过store中的state取值state.count,state.products分别来自于rootReducer
对两个模块的定义
const rootReducer = {
products: productsReducer,
count: countReducer
}
*/
const mapStateToProps=(state) => ({
count: state.count,
products: state.products,
});
/*
mapDispatchToProps映射store中的dispatch到组件的props
increment, incrementAsync分别为src/redux/actions/count的actions
二阶参数传入组件(Count)
*/
const mapDispatchToProps = { increment, incrementAsync };
count组建中使用redux
src/components/count.jsx
import React from "react";
import { increment, incrementAsync } from "../redux/actions/count";
import { connect } from "react-redux";
const Count = (props) => {
const addClick = () => {
props.increment(1);
};
const addClickAsync = () => {
props.incrementAsync(1);
};
return (
<div>
<button onClick={addClick}>count+1</button>
<button onClick={addClickAsync}>countAsync+1</button>
<div>count: {props.count}</div>
<div>productsLength:{props.products.length}</div>
</div>
);
};
const mapStateToProps = (state) => ({
count: state.count,
products: state.products,
});
const mapDispatchToProps = { increment, incrementAsync };
export default connect(mapStateToProps, mapDispatchToProps)(Count);
Products组建中使用redux
src/components/Products.jsx
import React from "react";
import { connect } from "react-redux";
import { addProduct } from "../redux/actions/products";
function Products(props) {
const addProductsClick = () => {
props.addProduct({ id: Date.now(), name: Date.now() });
};
return (
<div>
<button onClick={addProductsClick}>addProducts</button>
<ul>
{props.products.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
}
const mapStateToProps = (state, next) => ({ products: state.products });
const mapDispatchToProps = { addProduct };
export default connect(mapStateToProps, mapDispatchToProps)(Products);