亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

think-react-store--一款 react hooks 結合 context api 實現數據流處理工具

think-react-store

基于 react hooks 和 context api 实现的类似的 redux 的数据管理库。支持数据存储,方法调用,可以在 class 组件和 function 组件中使用,支持同步和异步的方法调用。

视频教程可以参考 https://coding.imooc.com/class/452.html ,3-5小节

安装

// 使用 npm
npm i --save think-react-store

// 使用yarn
yarn add think-react-store

api 介绍

api 作用 适合场景
StoreProvider 全局用的 provider app.js 或者单个模块的根文件
StoreContext 存储用的 Context function 组件和 class 组件均适用
useStoreHook store 钩子函数,包含state和dispatch function 组件
useStateHook 获取 state 用的 hook function 组件
useDispatchHook 进行事件派发的 hook function 组件
connect 添加属性和方法到组件中 function/class 组件

备注:

  • 参数 key 指的是,各个 context 导出时候对应的值,例如 export { default as user } from './user',那么 key 就是 user
  • 如果报语法错误,在检查原因后安装 babel 相关插件,例如 @babel/preset-react;另外建议不用 @babel/preset-env,因为 preset-env 会在运行时将 async/await 等进行转译;如果一定要使用,可以配置 targets 属性,类似这样子
"presets": [
  ["@babel/preset-env", {
    "targets": {
      "chrome": "70"
    },
    useBuiltIns: "usage"
  }],
  "@babel/preset-react"
],

1,创建 context

属性 含义
state state 属性
methods 方法,支持同步和异步两种写法,异步写法需要使用 async
reducers 支持同步方法
effects 支持异步方法,需要使用 async
// 创建 Contexts 目录

// user.js
export default {
  state: {
    id: 123,
    name: 'cc'
  },
  reducers: {
    setName(state, payload){
      return {
        ...state,
        ...payload
      }
    }
  },
  effects: {
    async setNameAsync(dispatch, state, payload){
      await new Promise(resolve=>setTimeout(resolve,1000))
      dispatch({
        type: 'setName',
        payload
      })
    }
  }
}

// index.js 合并 context
export { default as user } from './user'

2,配置 StoreProvider

import { StoreProvider } from 'think-react-store';
import * as store from './Contexts';

ReactDOM.render(
  <StoreProvider store={store}>
    <App />
  </StoreProvider>,
mountNode);

使用 connect (推荐)

备注:使用 connect 绑定的方法返回一个 promise 对象

const mapState = ({user:{id, name}}) => ({
  id,
  name
});
const mapDispatch = ({user:{setName, setNameAsync}}) => ({
  setName,
  setNameAsync
})
export default connect(mapState, mapDispatch)(DemoConnect)

// 使用
const handelClick = ()=>{
  props.setName({
    name: 'john'
  })
  .then(res=>{
    console.log(res)
  })
  .catch(err=>{
    console.log(err)
  })
}

3,在 function 组件中使用

import React, { useContext } from "react";
import { StoreContext, useStoreHook } from 'think-react-store';

export default function DemoFunc(){
  const {state, dispatch} = useContext(StoreContext)
  const {user:{id, name, setName, setNameAsync}} = useStoreHook()

  const handleName = ()=>{
    setName({
      name: '同步修改'
    })
  }

  const handleNameAsync = ()=>{
    setNameAsync({
      name: '异步修改'
    })
  }

  return (
    <div>
      <h1>function 类型组件</h1>
      <p>用户:name--{name}   id--{state.user.id}</p>
      <p><button onClick={handleName}>修改用户</button></p>
      <p><button onClick={handleNameAsync}>异步修改用户</button></p>
    </div>
  )
}

备注:function 组件中使用 @cpage/react-store ,有多种调用方法。

3.1 获取 state 数据

使用 useStoreHook(推荐使用)

import React, { useContext } from "react";
import { useStoreHook } from 'think-react-store';

const {user:{id, name, setName, setNameAsync}} = useStoreHook()

<div>用户:{name}</div>

使用 useContext + StoreContext

import React, { useContext } from "react";
import { StoreContext } from '@cpage/react-store';

// state 指的是所有 context 的 state
const {state, dispatch} = useContext(StoreContext)

<div>用户:{state.user.id}</div>

使用 useStateHook,useStateHook 接受一个参数,如果不传则返回所有 state,传递对应的 key 则返回对应的 state

import { useStateHook } from 'think-react-store';

// 获取所有的
const states = useStateHook()

// 获取单个的
const userState = useStateHook('user')

3.2 使用 dispatch

使用 useStoreHook(推荐使用),同步和异步的调用方式一样,只需要传递参数即可

import { useStoreHook } from 'think-react-store';

const {user:{id, name, setName, setNameAsync}} = useStoreHook()

getUser({
  name: '异步修改'
})

使用 useContext + StoreContext,如果是异步调用参数需要为函数

import React, { useContext } from "react";
import { StoreContext } from 'think-react-store';

// state 指的是所有 context 的 state
const {state, dispatch} = useContext(StoreContext)

// 同步
dispatch({
  key: 'user',
  type: 'setName',
  payload: {
    name: '同步数据'
  }
})

// 异步
dispatch(()=>({
  key: 'user',
  type: 'setNameAsync',
  payload: {
    name: '异步修改'
  }
}))

使用 useDispatchHook,useDispatchHook 接受一个参数,如果不传那么在使用 dispatch 使用需要携带上。如果是异步调用参数需要为函数

import { useDispatchHook } from 'think-react-store';

// 不带参数 key
const dispatchs = useDispatchHook()
dispatchs({
  key: 'user',
  type: 'setName',
  payload: {
    name: '同步数据'
  }
})

// 参数 key
const dispatchs = useDispatchHook('user')
dispatchs({
  type: 'setName',
  payload: {
    name: '同步数据'
  }
})

// 异步
dispatchs(()=>({
  type: 'setNameAsync',
  payload: {
    name: '异步修改'
  }
}))

4,在 class 组件中使用

在 class 组件中使用 dispatch 调用异步函数时候,this.context.dispatch 里面的参数是函数;使用 dispatch 调用同步函数时候,this.context.dispatch 里面的参数是函数是 json 对象。

import React from "react";
import { StoreContext } from 'think-react-store';

export default class DemoClass extends React.Component {
  static contextType = StoreContext;

  handleAuth = ()=>{
    this.context.dispatch({
      key: 'user',
      type: 'setName',
      payload: {
        name: '同步数据'
      }
    })
  }

  handleAuthAsync = ()=>{
    this.context.dispatch(()=>({
      key: 'user',
      type: 'setNameAsync',
      payload: {
        name: '异步数据'
      }
    }))
  }

  render() {
    return <div style={{border: '1px solid #9c9c9c'}}>
      <h1>class 类型组件</h1>
      <p>用户:{this.context.state.user.name}</p>
      <p><button onClick={this.handleAuth}>修改用户</button></p>
      <p><button onClick={this.handleAuthAsync}>异步修改用户</button></p>
    </div>;
  }
}

5,中间件

5.1 新增中间件文件

/**
 * 中间件参数
 * @param {Object} store store
 * @param {Object} prevState 更新前的state值
 * @param {Object} nextState 更新后的state值
 * @param {Object} action 派发的action
 */
export default function(store, prevState, nextState, action){
  console.log('----日志log-----')
  console.log(`修改前:${JSON.stringify(prevState)}`)
  console.log(`修改后:${JSON.stringify(nextState)}`)
}

5.2 使用中间件

备注:middleware 的类型为数组

<StoreProvider store={store} middleware={[log]}>
  
</StoreProvider>

6. loading

// 需要引入loading中间件
import loading from 'think-react-store/middlewares/loading'

// 配置
<StoreProvider store={store} middleware={[loading]}>
  
</StoreProvider>

// 使用
const mapState = ({user:{id, name}, loading}) => ({
  id,
  name,
  loading
});

<p>loading-getUser->{props.loading.user.getUser ? <span>true</span> : <span>false</span>}</p>
<p>loading-setNameAsync->{props.loading.user.setNameAsync ? <span>true</span> : <span>false</span>}</p>
點擊查看更多內容
6人點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
全棧工程師
手記
粉絲
128
獲贊與收藏
28

關注作者,訂閱最新文章

閱讀免費教程

感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消