How to connect redux store using useSelector() when input fields already mapped using useState()

后端 未结 1 465
自闭症患者
自闭症患者 2021-01-15 07:49

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

相关标签:
1条回答
  • 2021-01-15 08:52

    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
    
    
    0 讨论(0)
提交回复
热议问题