Как подключить избыточное хранилище с помощью useSelector (), когда поля ввода уже сопоставлены с помощью useState () - PullRequest
0 голосов
/ 21 мая 2019

Я играю с новой библиотекой React-Redux Hooks

У меня есть компонент реагирования, у которого есть два поля ввода, которые обновляются в хранилище реагирования с использованием useState () - desc и amount.Чтобы обновить изменения в хранилище при редуксе, когда поле было отредактировано, я использую событие onBlur и отправку вызова в хранилище притока.Это прекрасно работает.

Когда я хочу очистить поля от другого компонента, я бы хотел, чтобы это работало так же, как для функций на основе классов, через connect & map State для Props, но для этого с функциональным компонентом Iнеобходимо использовать useSelector ().Я не могу этого сделать, так как идентификаторы desc и amount уже используются 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))}
      />
      &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

1 Ответ

0 голосов
/ 22 мая 2019

РЕШЕНИЕ - С ПОЛНЫМ КОДОМ В ХРАНИЛИЩЕ *

Я разработал решение, используя useSelector (для отображения pendingItem части избыточного состояния в itemDef) и ловушку setEffect для применения useState к любому элементу состояния (из ввода)или itemDef (из состояния Redux - это происходит, когда приставка обновляется другим компонентом или кнопкой ADD ITEM TO INPUT)

Я разместил рабочий компонент ниже.Я также разместил это небольшое приложение, чтобы продемонстрировать, как использовать библиотеки activdt-redux как с компонентами на основе классов, так и с функциональными компонентами с использованием хуков

. Репозиторий 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...