当输入字段已使用 useState() 映射时,如何使用 useSelector() 连接 redux 存储 [英] How to connect redux store using useSelector() when input fields already mapped using useState()

查看:50
本文介绍了当输入字段已使用 useState() 映射时,如何使用 useSelector() 连接 redux 存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用新的 React-Redux Hooks 库

我有一个反应组件,它有两个输入字段,它们使用 useState() - desc 和数量更新到反应存储.为了在编辑字段时更新对 redux 存储的更改,我使用 onBlur 事件并调用调度到 redux 存储.效果很好.

当我想从另一个组件中清除字段时,我希望它以与通过 connect & 基于类的函数相同的方式工作.将状态映射到道具,但是使用功能组件将状态映射到这个,我需要使用 useSelector().我不能这样做,因为标识符 desc 和数量已经被 useState() 使用

我在这里遗漏了什么?

import { useDispatch, useSelector } from "react-redux"import {defineItem, clearItem } from "../store/actions"const ItemDef = 道具 =>{const dispatch = useDispatch()const [desc, setDesc] = useState(itemDef.desc)const [amount, setAmount] = useState(itemDef.amount)//MAPSTATETOPROPS//当 REDUX 存储从另一个组件更改时,我希望更新这些值//THESE LINES WILL CAUSE ERROR to effect - 标识符已经被声明const desc = useSelector(state => state.pendingItem.desc)const amount = useSelector(state => state.pendingItem.amount)返回 (<div><p>在下方定义要添加的新项目 - 在单击添加项目之前</p><输入值={desc}类型=文本"名称=desc"占位符="项目描述"onChange={e =>setDesc(e.target.value)}//使用 onBlur 事件,以便仅在字段失去焦点时将更改提交到存储onBlur={e =>dispatch(defineItem(desc, amount))}/>&nbsp;<输入价值={金额}类型=数字"名称=金额"占位符=金额"onChange={e =>setAmount(e.target.value)}//使用 onBlur 事件,以便仅在字段失去焦点时将更改提交到存储onBlur={e =>{调度(定义项目(描述,金额))}}/>

)}导出默认 ItemDef

解决方案

SOLUTION - WITH FULL CODE IN REPOSITORY

我通过使用 useSelector(将 redux state 的 pendingItem 部分映射到 itemDef)和 setEffect 钩子将 useState 应用到 state item(来自输入)或 itemDef(来自 Redux State - 当 redux 更新时会发生这种情况)制定了一个解决方案通过另一个组件或通过添加项目到输入按钮)

我已经在下面发布了工作组件.我还发布了这个小应用程序来演示如何使用带有基于类的组件和使用钩子的功能组件的 reacdt-redux 库

存储库是 https://github.com/Intelliflex/hiresystem

//**********************************************************************************************************//***** ITEMDEF 组件 - 允许输入新项目(从 HireList 表中的按钮调度)****//**********************************************************************************************************import React, { useState, useEffect, useRef } from 'react'import { useDispatch, useSelector } from 'react-redux'import {defineItem, clearItem } from '../store/actions'从'lodash'导入_const ItemDef = 道具 =>{//从 REDUX 商店引入调度const dispatch = useDispatch()//定义选择器 - 等同于 MAPSTATETOPROPSconst { itemDef } = useSelector(state => ({itemDef:state.pendingItem}))const [item, setItem] = useState({ desc: '', amount: 0 })const onChange = e =>{设置项({...物品,[e.target.name]: e.target.value})}const prevItem = useRef(item)useEffect(() => {//我们需要根据是否直接更改存储或输入表单更改有条件地更新if (!_.isEqual(item, prevItem.current)) {//输入已更改设置项目(项目)} else if (!_.isEqual(item, itemDef)) {//REDUX 状态已更改设置项目(项目定义)}prevItem.current = 项目}, [item, itemDef])//注意:item和ItemDef作为第二个参数传入,以便使用setItemconst clearIt = e =>{调度(清除项目())}const addIt = e =>{dispatch(defineItem({ desc: '我的新项目', 数量: 222 }))}返回 (<div><p>在下方定义要添加的新项目 - 在单击添加项目之前</p><输入值={item.desc}类型='文本'名称='desc'占位符='物品描述'onChange={onChange}//使用 onBlur 事件,以便仅在字段失去焦点时将更改提交到存储onBlur={e =>调度(定义项目(项目))}/>&nbsp;<输入价值={item.amount}类型='数字'名称='金额'占位符='金额'onChange={onChange}//使用 onBlur 事件,以便仅在字段失去焦点时将更改提交到存储onBlur={e =>调度(定义项目(项目))}/>&nbsp;<button onClick={clearIt}>CLEAR ITEM</button>&nbsp;<button onClick={addIt}>将项目添加到输入</button>

)}导出默认 ItemDef

I am playing around with the new React-Redux Hooks library

I have an react component that has two input fields that update to the react store using useState() - desc and amount. In order to update changes to the the redux store when field has been edited I use onBlur event and call dispatch to the redux store. That works fine.

When I want to clear the fields from another component I would like this to work in same manner as for class based functions via connect & map State to Props, however to to this with functional component I need to utilise useSelector(). I cannot do this as the identifiers desc and amount are already used by useState()

What am I missing here?

import { useDispatch, useSelector } from "react-redux"
import { defineItem, clearItem } from "../store/actions"

const ItemDef = props => {
  const dispatch = useDispatch()

  const [desc, setDesc] = useState(itemDef.desc)
  const [amount, setAmount] = useState(itemDef.amount)

  //MAPSTATETOPROPS
  //I WANT TO HAVE THESE VALUES UPDATED WHEN REDUX STORE CHANGES FROM ANOTHER COMPONENT
  //THESE LINES WILL CAUSE ERROR to effect - identifier has already been declared
  const desc = useSelector(state => state.pendingItem.desc)
  const amount = useSelector(state => state.pendingItem.amount)

  return (
    <div>
      <p>Define new items to be added below - before clicking Add Item</p>
      <input
        value={desc}
        type="text"
        name="desc"
        placeholder="Description of Item"
        onChange={e => setDesc(e.target.value)}
        //Use onBlur Event so that changes are only submitted to store when field loses focus
        onBlur={e => dispatch(defineItem(desc, amount))}
      />
      &nbsp;
      <input
        value={amount}
        type="number"
        name="amount"
        placeholder="Amount"
        onChange={e => setAmount(e.target.value)}
        //Use onBlur Event so that changes are only submitted to store when field loses focus
        onBlur={e => {
          dispatch(defineItem(desc, amount))
        }}
      />
    </div>
  )
}

export default ItemDef

解决方案

SOLUTION - WITH FULL CODE IN REPOSITORY

I worked out a solution by using useSelector (to map pendingItem part of redux state to itemDef) and the setEffect hook to apply useState to either state item (from input) or itemDef (from Redux State - this happens when redux is updated by another component or through the ADD ITEM TO INPUT button)

I have posted the working component below. I have also posted this small application to demonstrate how to use reacdt-redux libraries with both class based components and fuinctional components using hooks

The repository is https://github.com/Intelliflex/hiresystem

//**************************************************************************************************
//***** ITEMDEF COMPONENT - Allow entry of new Items (dispatched from button in HireList Table) ****
//**************************************************************************************************
import React, { useState, useEffect, useRef } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { defineItem, clearItem } from '../store/actions'
import _ from 'lodash'

const ItemDef = props => {
  //BRING IN DISPATCH FROM REDUX STORE
  const dispatch = useDispatch()

  //DEFINE SELECTOR - EQUIV TO MAPSTATETOPROPS
  const { itemDef } = useSelector(state => ({
    itemDef: state.pendingItem
  }))

  const [item, setItem] = useState({ desc: '', amount: 0 })

  const onChange = e => {
    setItem({
      ...item,
      [e.target.name]: e.target.value
    })
  }

  const prevItem = useRef(item)
  useEffect(() => {
    //WE NEED TO CONDITIONALLY UPDATE BASED ON EITHER STORE BEING CHANGED DIRECTLY OR INPUT FORM CHANGING
    if (!_.isEqual(item, prevItem.current)) {
      //INPUT HAS CHANGED
      setItem(item)
    } else if (!_.isEqual(item, itemDef)) {
      //REDUX STATE HAS CHANGED
      setItem(itemDef)
    }
    prevItem.current = item
  }, [item, itemDef]) //Note: item and ItemDef are passed in as second argument in order to use setItem

  const clearIt = e => {
    dispatch(clearItem())
  }

  const addIt = e => {
    dispatch(defineItem({ desc: 'MY NEW ITEM', amount: 222 }))
  }

  return (
    <div>
      <p>Define new items to be added below - before clicking Add Item</p>
      <input
        value={item.desc}
        type='text'
        name='desc'
        placeholder='Description of Item'
        onChange={onChange}
        //Use onBlur Event so that changes are only submitted to store when field loses focus
        onBlur={e => dispatch(defineItem(item))}
      />
      &nbsp;
      <input
        value={item.amount}
        type='number'
        name='amount'
        placeholder='Amount'
        onChange={onChange}
        //Use onBlur Event so that changes are only submitted to store when field loses focus
        onBlur={e => dispatch(defineItem(item))}
      />
      &nbsp;
      <button onClick={clearIt}>CLEAR ITEM</button>
      &nbsp;
      <button onClick={addIt}>ADD ITEM TO INPUT</button>
    </div>
  )
}

export default ItemDef

这篇关于当输入字段已使用 useState() 映射时,如何使用 useSelector() 连接 redux 存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆