react跨组件通信及react-redux 使用

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

基本概念:

  1. 初始化数据对象state;
  2. 提供用于修改数据的操作action;
  3. 创建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 挂载渲染函数

说明:

  1. 使用createSotre方法声明创建store对象。
  2. getState()返回定义的数据对象值。
  3. dispatch()分发一个事件,有reducer函数接受处理,包括处理类型type、和需要传输的数据
  4. 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;

其他:

  1. unsubscribe = store.subscribe(render) 返回取消监听的函数,调用后取消监听变化。
  2. redux中的combineReducers()方法用于合并多个reducers(实例中处理比较简单,业务中复杂的处理则需要分模块);

react-redux

使得各部分组件从store读取数据,并可分发更新操作dispatch action更新数据。

使用示例

安装redux react-redux

npm install react-redux

要点说明:

  1. Provider 提供上下文环境,挂载数据。
  2. connect(mapStateToProps?,mapDispatchToProps?,mergeProps?,options?) 包裹react组件,使得provider提供的数据可用。
    1. mapStateToProps(state,ownProps)订阅到store数据的更新映射到组件的props;任何时候更新都会调用。
    2. 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";

你可能感兴趣的:(react)