react-redux 使用说明,加一些个人理解。
react组件通信,请参考另一篇文章react组件通信
为了解决不同组件之间的数据共享,react提供了context解决方案,而redux
提供了灵活、可靠地处理数据交互。
context
使用创建MyContext.js
,作为想要共享数据组件的关联的对象。
import React from 'react';
const UserContext = React.createContext({
info:{},
updateInfo:()=>{}
});
export default UserContext;
在父组件提供共享值供子组件消费context
,创建index.js
import React,{useState} from 'react';
// 组件
import ChildOne from './childOne';
import ChildTwo from './childTwo';
// context
import UserContext from './MyContext';
export default function ContextDemo(){
const [info,setInfo] = useState({
name:"test"
});
// 更新共享值
function updateInfo(item){
setInfo((preVal)=>{
return {
...preVal,
...item
}
});
}
// 用父组件的state作为数据源
return(<div>
<UserContext.Provider value={{
info:info,
updateInfo:updateInfo
}}>
<p>ContextDemo</p>
<div>
<ChildOne />
</div>
<div>
<ChildTwo />
</div>
</UserContext.Provider>
</div>);
}
在各子组件中的属性使用以及动态更新,childOne.js
/childTwo.js
childOne.js
// child-one.js
import React,{useContext} from 'react';
import UserContext from './MyContext';
export default function ChildOne(){
const MyContext = useContext(UserContext);
return (<div>
<p>ChildOne</p>
<span>{MyContext.info.name}</span>
</div>)
}
childTwo.js
// childTwo.js
import React,{useContext} from 'react';
import UserContext from './MyContext';
export default function ChildTwo(){
const MyContext = useContext(UserContext);
return (<div>
<p>child-two</p>
<button onClick={()=>MyContext.updateInfo({name:"admin"})}>更新</button>
</div>);
}
redux
基本概念:
state
;action
;reducer
关联数据对象、关联的数据处理;reducers.js
let num=0;
export default (state=[],action)=>{
debugger;
let {type,name,id} = action;
switch(type){
case "ADD":
state.push({
id:num++,
name:name
});
return state;
case "DELETE":
let index = state.findIndex(item=>item.id===id);
state.splice(index,1);
return state;
default:
return state;
}
}
index.js
挂载渲染函数
说明:
createSotre
方法声明创建store对象。getState()
返回定义的数据对象值。dispatch()
分发一个事件,有reducer
函数接受处理,包括处理类型type
、和需要传输的数据subscribe()
接受一个函数用于监听变化。import React from "react";
import ReactDOM from "react-dom";
import {createStore} from 'redux';
import reducers from './redux/reducers';
import ShowInfo from './redux';
let store = createStore(reducers);
const render = ()=> ReactDOM.render(<div>
<ShowInfo
infos={store.getState()}
addInfo={(name)=>store.dispatch({type:"ADD",name:name})}
deleteInfo={(id)=>store.dispatch({type:"DELETE",id:id})} />
</div>,
document.getElementById('root')
);
render();
store.subscribe(render);
ShowInfo.js
通过props
正常取用对象值、调用方法即可。
import React,{useState} from 'react';
import PropTypes from 'prop-types';
function ShowInfo(props){
let [name,setName] = useState(null);
let {infos,addInfo,deleteInfo} = props;
return (<div>
{infos.map(item=><React.Fragment>
<p key={item.id}>{item.name} <span onClick={e=>deleteInfo(item.id)}>-</span></p>
</React.Fragment>)}
<input value={name} onChange={e=>setName(e.target.value)} />
<button onClick={e=>addInfo(name)}>添加</button>
</div>);
}
ShowInfo.propTypes = {
infos:PropTypes.array.isRequired,
addInfo:PropTypes.func.isRequired,
deleteInfo:PropTypes.func.isRequired
}
export default ShowInfo;
其他:
unsubscribe = store.subscribe(render)
返回取消监听的函数,调用后取消监听变化。redux
中的combineReducers()
方法用于合并多个reducers
(实例中处理比较简单,业务中复杂的处理则需要分模块);react-redux
使得各部分组件从store
读取数据,并可分发更新操作dispatch action
更新数据。
安装redux react-redux
npm install react-redux
要点说明:
Provider
提供上下文环境,挂载数据。connect(mapStateToProps?,mapDispatchToProps?,mergeProps?,options?)
包裹react组件,使得provider
提供的数据可用。
mapStateToProps(state,ownProps)
订阅到store
数据的更新映射到组件的props
;任何时候更新都会调用。mapDispatchToProps(object||(dispatch,ownProps))
定义store
数据更新的方法映射到组建的props
store.js
初始化数据对象
import {createStore} from 'redux';
// action type
import {UPDATE_USER,ADD_USER} from './actionType';
const initState = {
allUser:[],
userObj:{}
}
// store 对象处理
function reducerUser(state=initState,action){
switch(action.type){
case ADD_USER:{
const info = action.info;
return {
...state,
allUser:[...state.allUser,info],
userObj:{
}
}
}
case UPDATE_USER:{
const {id,status} = action.info;
const index = state.allUser.findIndex(obj=>obj.id === id);
let target = state.allUser[index];
state.allUser.splice(index,1,{
...target,
status:status
});
return {
...state,
allUser:[...state.allUser],
userObj:{
}
}
}
default:
return state;
}
}
export default createStore(reducerUser);
APP.js
挂载到根组件上,提供在所有子组件可用。
import React from 'react';
import {Provider} from 'react-redux';
import store from './redux/store';
// 组件
import ShowInfo from './component/ShowInfo';
import UserInfo from './component/UserInfo';
export default function ReduxDemo(){
return (<div>
<Provider store={store}>
<ShowInfo />
<UserInfo />
</Provider>
</div>);
}
UserInfo.js
用于添加用户数据
import React,{useState} from 'react';
import {connect} from 'react-redux';
import {addUser} from '../redux/action';
function UserInfo(props){
const [name,setName] = useState();
const [age,setAge] = useState();
function handleClick(e){
e.stopPropagation();
props.addUser({
name:name,
age:age,
status:false
});
//
setName("");
setAge("");
}
return(<div>
<label>
<span>姓名:</span>
<input type="text" value={name} onChange={e=>setName(e.target.value)} />
</label>
<label>
<span>年龄</span>
<input type="text" value={age} onChange={e=>setAge(e.target.value)} />
</label>
<button className="btn-update" onClick={handleClick}>添加</button>
</div>);
}
export default connect(null,{addUser})(UserInfo);
ShowInfo.js
用于展示用户列表数据以及各自数据更新操作
说明:
/**
* 用户组件信息
*/
import React from 'react';
import PropTypes from 'prop-types';
import {connect} from 'react-redux';
import {updateUser} from '../redux/action';
function ShowInfo(props){
return(<div>
<ul>
{props.allUser.map((item,index)=><InfoItem key={index} {...item} fn={()=>props.updateUser({id:item.id,status:!item.status})} />)}
</ul>
</div>);
}
// 单人的信息展示
function InfoItem(props){
function handleClick(e){
e.stopPropagation();
props.fn();
}
return(<li onClick={handleClick} style={{color:props.status?"#f34234":"#2b34ff"}}>
<div style={{border:"1px solid #eee"}}>
<p>名称:{props.name}</p>
<p>年龄:{props.age}</p>
</div>
</li>);
}
// 映射外部数据源给组件的props
const mapStateToProps = (state,ownProps)=>{
// const {} = state.allUser;
return {
allUser:state.allUser
}
}
// connect 参数
export default connect(mapStateToProps,{updateUser})(ShowInfo);
action.js
定义操作数据对象的方法。
import {ADD_USER,UPDATE_USER} from './actionType';
let id = 0;
// 添加个人信息
export const addUser = item=>({
type:ADD_USER,
info:{
id:id++,
...item
}
})
// 修改个人信息
export const updateUser = item=>{
return {
type:UPDATE_USER,
info:{
...item,
}
}
}
actionType.js
’ 定义事件的类型名称。
export const UPDATE_USER = "UPDATE_USER";
export const ADD_USER = "ADD_USER";