Reactjs 当输入字段已使用useState()映射时,如何使用useSelector()连接redux存储
我正在玩新的React Redux Hooks库 我有一个react组件,它有两个输入字段,使用useState()和amount更新react存储。为了在编辑字段时更新对redux存储的更改,我使用onBlur事件并调用dispatch到redux存储。那很好 当我想从另一个组件中清除字段时,我希望通过connect&map State to Props以与基于类的函数相同的方式工作,但是要使用功能组件将状态映射到该字段,我需要使用useSelector()。我不能这样做,因为useState()已经使用了标识符desc和amount 我错过了什么Reactjs 当输入字段已使用useState()映射时,如何使用useSelector()连接redux存储,reactjs,redux,react-redux,react-hooks,Reactjs,Redux,React Redux,React Hooks,我正在玩新的React Redux Hooks库 我有一个react组件,它有两个输入字段,使用useState()和amount更新react存储。为了在编辑字段时更新对redux存储的更改,我使用onBlur事件并调用dispatch到redux存储。那很好 当我想从另一个组件中清除字段时,我希望通过connect&map State to Props以与基于类的函数相同的方式工作,但是要使用功能组件将状态映射到该字段,我需要使用useSelector()。我不能这样做,因为useState
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))}
/>
<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
从“react-redux”导入{useDispatch,useSelector}
从“./store/actions”导入{defineItem,clearItem}
const ItemDef=props=>{
const dispatch=usedpatch()
const[desc,setDesc]=useState(itemDef.desc)
const[amount,setAmount]=useState(itemDef.amount)
//MAPSTATETOPROPS
//我想在REDUX存储区从另一个组件更改时更新这些值
//这些行将导致错误生效-标识符已声明
const desc=useSelector(state=>state.pendingItem.desc)
const amount=useSelector(state=>state.pendingItem.amount)
返回(
在下面定义要添加的新项目-单击“添加项目”之前
setDesc(e.target.value)}
//使用onBlur事件,这样更改仅在字段失去焦点时提交到存储
onBlur={e=>dispatch(defineItem(desc,amount))}
/>
setAmount(e.target.value)}
//使用onBlur事件,这样更改仅在字段失去焦点时提交到存储
onBlur={e=>{
发货(定义项目(描述、金额))
}}
/>
)
}
导出默认项定义
解决方案-存储库中包含完整代码
我通过使用useSelector(将redux状态的pendingItem部分映射到itemDef)和setEffect钩子将useState应用到状态项(来自输入)或itemDef(来自redux状态-当redux由另一个组件更新或通过ADD item to input按钮更新时,会发生这种情况)制定出一个解决方案
我已经在下面发布了工作组件。我还发布了这个小应用程序来演示如何将reactt redux库与基于类的组件和使用挂钩的功能组件一起使用
存储库是
//**************************************************************************************************
//*****ITEMDEF组件-允许输入新项目(从HireList表中的按钮发送)****
//**************************************************************************************************
从“React”导入React,{useState,useffect,useRef}
从“react redux”导入{useDispatch,useSelector}
从“../store/actions”导入{defineItem,clearItem}
从“lodash”导入
const ItemDef=props=>{
//从REDUX商店引入调度
const dispatch=usedpatch()
//定义选择器-等效于MapStateTrops
const{itemDef}=useSelector(状态=>({
itemDef:state.pendingItem
}))
const[item,setItem]=useState({desc:'',金额:0})
const onChange=e=>{
设定项({
…项目,
[e.target.name]:e.target.value
})
}
const previitem=useRef(项目)
useffect(()=>{
//我们需要根据直接更改的存储或输入表单的更改进行有条件的更新
如果(!\u.isEqual(项,前项,当前)){
//输入已更改
设置项目(项目)
}如果(!.isEqual(item,itemDef)){
//REDUX状态已更改
setItem(itemDef)
}
previItem.current=项目
},[item,itemDef])//注意:item和itemDef作为第二个参数传入,以便使用setItem
常数clearIt=e=>{
分派(clearItem())
}
常数addIt=e=>{
分派(定义项({desc:'我的新项目',金额:222}))
}
返回(
在下面定义要添加的新项目-单击“添加项目”之前
调度(定义项(项))}
/>
调度(定义项(项))}
/>
清除项
将项目添加到输入
)
}
导出默认项定义
在这种情况下,lodash的用途是什么?我一点也不熟悉all@mph85他用它来比较对象:u.isEqual(item,previitem.current..lodash是一个带有实用函数的库。只要读一分钟文档,你就会理解它=)
//**************************************************************************************************
//***** 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))}
/>
<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))}
/>
<button onClick={clearIt}>CLEAR ITEM</button>
<button onClick={addIt}>ADD ITEM TO INPUT</button>
</div>
)
}
export default ItemDef