前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用useSelector useDispatch 替代connect

使用useSelector useDispatch 替代connect

作者头像
w候人兮猗
发布2020-07-01 16:56:34
4.8K0
发布2020-07-01 16:56:34
举报
文章被收录于专栏:w候人兮猗的博客

前言

随着react hooks越来越火,react-redux也紧随其后发布了7.1(https://react-redux.js.org/api/hooks#using-hooks-in-a-react-redux-app)版本

首先是几个API

  • useSelector()
代码语言:javascript
复制
const result : any = useSelector(selector : Function, equalityFn? : Function)

主要作用: 从reduxstore对象中提取数据(state)。

注意:选择器函数应该是纯函数,因为它可能在任意时间点多次执行。

代码语言:javascript
复制
import React from 'react'
import { useSelector } from 'react-redux'

export const CounterComponent = () => {
  const counter = useSelector(state => state.counter)
  return <div>{counter}</div>
}
  • useDispatch()
代码语言:javascript
复制
const dispatch = useDispatch()

返回Redux store中对dispatch函数的引用。你可以根据需要使用它。

代码语言:javascript
复制
import React from 'react'
import { useDispatch } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const dispatch = useDispatch()

  return (
    <div>
      <span>{value}</span>
      <button onClick={() => dispatch({ type: 'increment-counter' })}>
        Increment counter
      </button>
    </div>
  )
}

将回调使用dispatch传递给子组件时,建议使用来进行回调useCallback,因为否则,由于更改了引用,子组件可能会不必要地呈现。

代码语言:javascript
复制
import React, { useCallback } from 'react'
import { useDispatch } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const dispatch = useDispatch()
  const incrementCounter = useCallback(
    () => dispatch({ type: 'increment-counter' }),
    [dispatch]
  )

  return (
    <div>
      <span>{value}</span>
      <MyIncrementButton onIncrement={incrementCounter} />
    </div>
  )
}

export const MyIncrementButton = React.memo(({ onIncrement }) => (
  <button onClick={onIncrement}>Increment counter</button>
))
  • useStore()
代码语言:javascript
复制
const store = useStore()

这个Hook返回redux <Provider>组件的store对象的引用。

这个钩子应该不长被使用。useSelector应该作为你的首选。但是,有时候也很有用。来看个例子:

代码语言:javascript
复制
import React from 'react'
import { useStore } from 'react-redux'

export const CounterComponent = ({ value }) => {
  const store = useStore()

  // 仅仅是个例子! 不要在你的应用中这样做.
  // 如果store中的state改变,这个将不会自动更新
  return <div>{store.getState()}</div>
}

dva中如何使用

dvadva@2.6.0[1]的beta版本发布了这几个API,如果我们想使用他,首先安装指定版本的

代码语言:javascript
复制
yarn add dva@2.6.0-beta.19 
// or
npm install dva@2.6.0-beta.19

并且这样使用

代码语言:javascript
复制
import { useSelector, useDispatch } from 'dva';

如果不想升级dva版本的话我们需要安装

代码语言:javascript
复制
yarn add react-redux@7.1.0

并且这样使用

代码语言:javascript
复制
import { useSelector, useDispatch } from 'react-redux';

首先先看原始dva的写法 先定义一个user model

代码语言:javascript
复制
// 1.user.js ==>model
export default {
  namespace: 'user',
  state: {
    userInfo:null,
  },
  effects: {
      *fetchUser({paylaod},{call,put}){
          const res = yield(api,payload)
          yield put({
            type: 'save',
            payload: {
                userInfo:res   
            },
          });
      }
  },
  reducers:{
      save(state, { payload }) {
        return {
            ...state,
            ...payload,
        };
      },
  }
}

然后在页面中使用

代码语言:javascript
复制
import {connect} from 'dva'

const Home = props=>{
    // 获取数据
    const {user,loading,dispatch} = props

    // 发起请求
    useEffect(()=>{
        dispatch({
            type:'user/fetchUser',payload:{}
        })
    },[])

    // 渲染页面
    if(loading) return <div>loading...</div>
    return (
        <div>{user.name}<div>
    )
}

export default connect(({loading,user})=>({
    loading:loading.effects['user/fetchUser'],
    user:user.userInfo
}))(Home)

connect这个高阶组件里定义了太多东西,这种写法太恶心了。 如果太多数据从props获取的话,connect里堆了太多代码

下面我们使用useDispatch useSelector 优化上面的代码

代码语言:javascript
复制
import {useDispatch,useSelector} from 'dva'

const Home = props=>{

    const dispatch = useDispatch()

    const loadingEffect = useSelector(state =>state.loading);
    const loading = loadingEffect.effects['user/fetchUser'];
    const user = useSelector(state=>state.user.userInfo)

    // 发起请求
    useEffect(()=>{
        dispatch({
            type:'user/fetchUser',payload:{}
        })
    },[])

    // 渲染页面
    if(loading) return <div>loading...</div>
    return (
        <div>{user.name}<div>
    )
}

export default Home

使用useSelector useDispatch 替代connect

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019年12月12日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • dva中如何使用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档