12.redux-store使用

创建store

添加依赖

npm install react-redux redux redux-thunk

创建reducer

redux/reducer/fetchState.ts

const initialState = false;//初始状态

const fetchState = (state = initialState, action:any) => {
    switch (action.type) { 
        case 'set_fetch_state': //操作类型
            return action.payload; //返回状态
        default:
            return state;
    }
};

export default fetchState; //导出reducer

redux/reducer/map.ts


const initialState = {
    name: null,
    info: {
        age: null,
        address: null
    }
}; //初始状态

const map = (state = initialState, action:any) => {
    switch (action.type) { //操作类型
        case 'update_name':
            return { ...state, name: action.payload };//payload是操作参数,返回新的状态
        case 'update_age':
            return { ...state, info: { ...state.info, age: action.payload } };
        case 'update_address':
            return { ...state, info: { ...state.info, address: action.payload } };
        case 'init_state':
             return action.payload;
        default:
            return state;
    }
};

export default map;//导出reducer

redux/reducer/index.ts

import { combineReducers } from 'redux'; 
import map  from './map';
import fetchState from './fetchState';
const reducers = combineReducers( //合并两个reducer为一个reducer
	{
		map,
		fetchState
	});
export default reducers; //导出合并后的reducer

创建action

redux/stateAction.ts

//store.dispatch(stateAction.xxx)来修改状态
export const update_name = (name: string) => { 
    return {
        type: 'update_name', //操作类型
        payload: name //操作参数
    }
}
export const update_age = (age: string) => {
    return {
        type: 'update_age',
        payload: age
    }
}
export const update_address = (address: string) => {
    return {
        type: 'update_address',
        payload: address
    }
}

export const init_state = (state: any) => {
    return {
        type: 'init_state',
        payload: state
    }
}

export const set_fetch_state = (state: boolean) => {
    return {
        type: 'set_fetch_state',
        payload: state
    }
}

创建store

App.tsx

import {
  applyMiddleware as applyReduxMiddleware,
  createStore as createReduxStore
} from 'redux';
import thunk from 'redux-thunk';//异步dispatch使用,之后会介绍
import reducers from './redux/reducer';//导入reducer
const reduxMiddlewares = [thunk];
//创建store
const store = createReduxStore(
  reducers,//reducer
  undefined, //初始值
  applyReduxMiddleware(...reduxMiddlewares)//store中间处理
);

创建组件

创建组件

component/MapComponent.jsx

import React, { Component } from 'react';
import {
    Text,
    View,
    Button
  } from 'react-native'; //组件库中导入组件

export default class MapComponent extends React.Component {//继承自React.Component


    render() { //render方法渲染组件
        const {
            client,
            map,
            fetchState,
            update_name,
            update_age,
            update_address 
        } = this.props;//获取所有组件属性

        if (!fetchState) {
            return <Text>Loading...</Text>;//正在获取数据,显示加载中
        }else{
            return (//获取数据完成,展示数据
                <View>
                    <Text>Map Component</Text>
                    <Text>Name: {map.name}</Text>
                    <Text>Age: {map.info.age}</Text>
                    <Text>Address: {map.info.address}</Text>
                    <Button onPress={() => update_name('Jane')} title='Update Name'/>
                    <Button onPress={() => update_age('200')} title='Update Age'/>
                    <Button onPress={() => update_address('sx')} title='Update Address'/>
                </View>
            );
        }
    }
}

store添加到上下文

App.tsx

//Provider放在最外面,所有在Provider中的组件都可以获得store
import { Provider } from 'react-redux';
return (
    <Provider store={store}>
	</Provider>);

store状态以及dispatch方法映射到组件属性

Context.js

export function withContext(Component)
{
	return (props) => ( //prop传递给组件
		<Component {...props} />
	);
}

修改component/MapComponent.jsx

import { withContext } from '../Context'; //导入Context
import { connect } from 'react-redux';//connect用于将上下文中的store根据map方法映射为组件的props
import * as stateAction from '../redux/stateAction';//导入action

const mapStateToProps = (state) => {//store.state映射到字段类型属性
    return {
        map: state.map,//字段属性map
        fetchState: state.fetchState,
    };
};

const mapDispatchToProps = (dispatch) => {//store.dispatch映射到方法类型属性
    return {
        update_name: (name) => {//方法属性update_name
            dispatch(stateAction.update_name(name));
        },
        update_age: (age) => {
            dispatch(stateAction.update_age(age));
        },
        update_address: (address) => {
            dispatch(stateAction.update_address(address));
        },
    };
};

const Container = withContext(connect(
    mapStateToProps,
    mapDispatchToProps
)(MapComponent));//映射属性到组件

export default Container;//导出映射后的组件

组件中使用dispatch方法

修改component/MapComponent.jsx

export default class MapComponent extends React.Component {
    render() { 
        const {
            client,
            map,
            fetchState,
            update_name,
            update_age,
            update_address 
        } = this.props;

        if (!fetchState) {
            return <Text>Loading...</Text>;
        }else{
            return (
                <View>
                    <Text>Map Component</Text>
                    <Text>Name: {map.name}</Text>
                    <Text>Age: {map.info.age}</Text>
                    <Text>Address: {map.info.address}</Text>
                    <Button onPress={() => update_name('Jane')} title='Update Name'/>//使用dispatch方法update_name修改name
                    <Button onPress={() => update_age('200')} title='Update Age'/>
                    <Button onPress={() => update_address('sx')} title='Update Address'/>
                </View>
            );
        }
    }
}

组件属性加类型限制

添加依赖prop-types

npm install prop-types

propTypes.js: 创建自定义类型限制

import PropTypes from 'prop-types';

export const map_component = PropTypes.shape({
		name: PropTypes.string.isRequired,
        info: PropTypes.shape({
            age: PropTypes.string.isRequired,
            address: PropTypes.string.isRequired,
    }).isRequired,
});

修改component/MapComponent.jsx

import PropTypes from 'prop-types';
import * as propTypes from './propTypes';

MapComponent.propTypes =
{
    client      : PropTypes.any.isRequired, //任意类型
    map         : propTypes.map_component.isRequired, //自定义限制
    fetchState : PropTypes.bool.isRequired, //bool
    update_name : PropTypes.func.isRequired,//函数
    update_age  : PropTypes.func.isRequired,//函数
    update_address: PropTypes.func.isRequired,//函数
};

创建客户端

客户端一般用于处理异步函数,比如调用接口

store添加到客户端

Client.js

//store添加到客户端之后客户端就可以获取store的状态以及调用dispatch方法
let store;
export default class Client
{
	static init(data)
	{
		store = data.store;
	}
}

App.tsx

import Client from './Client';
Client.init({ store });

创建客户端

Client.js

export default class Client
{
    _url;

    constructor(
		{
			url,
		}
	)
	{
        this._url = url;
    }
}

App.tsx

let client = new Client({ url: 'www.google.com' });

客户端添加到上下文

App.tsx

import Context from './Context';//获取Context
//Context.Provider设置客户端到上下文中
return (
    <Provider store={store}>
      <Context.Provider value={client}>
	  </Context>
	</Provider>)

客户端映射到组件属性

修改Context.js

import React from 'react';

const Context = React.createContext(null); //创建Context

export default Context;

export function withContext(Component)
{
	//从Context上下文中获取客户端并映射到组件的属性中
	return (props) => ( 
		<Context.Consumer>
			{(client) => <Component {...props} client={client} />}
		</Context.Consumer>
	);
}

创建客户端方法

修改Client.js

import * as stateAction from './redux/stateAction';

export default class Client
{
    getMap(){
        store.dispatch(this.getMapData());//dispatch异步方法,在store必须配置thunk才能使用
    }

    getMapData(){
		//dispatch异步方法,返回一个方法,方法的参数是store的dispatch和state,结果类型是Promise
        return async (dispatch, getState) => {
            dispatch(stateAction.set_fetch_state(false));//设置正在获取数据状态为false
            let data=await new Promise((resolve, reject) => { //异步方法获取需要展示的数据
                setInterval(() => {
                    resolve({
                        name: 'John Doe',
                        info: {
                            age: '30',
                            address: '123 Main St',
                        },
                    });
                }, 1000);
            });
            dispatch(stateAction.init_state(data)); //设置需要展示的数据
            dispatch(stateAction.set_fetch_state(true));//设置正在获取数据状态为true
          };
    }
}

组件中使用客户端方法

class MapComponent extends React.Component {
	//当组件挂载前执行
    componentDidMount() { 
        const { client }	= this.props; //从属性中获取客户端
        client.getMap(); //调用dispatch异步方法获取数据并更新ui
    }
}

组件效果展示

添加组件到ui

App.tsx

import MapComponent from './component/MapComponent';
return (
    <Provider store={store}>
      <Context.Provider value={client}>
		<MapComponent/>
	  </Context>
	</Provider>)

测试

在这里插入图片描述

1s后加载完成
在这里插入图片描述

点击按钮后Name,Age,Address变更

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值