反应挂钩:无法更新功能组件内部的状态

时间:2019-10-15 15:17:01

标签: javascript reactjs state react-hooks

我是React的新手,正在尝试弄清楚如何制作电话簿。我已经走了很远,但是遇到了一个我无法解决的问题。我正在使用React Hooks。

一切正常,除了当我在setNewNumber('')常量的setNewName('')末尾调用addPerson()filteredEntries函数时。 我想将''中的其他代码运行完毕后,将表单中的输入字段重置为空字符串(addPerson(),但是由于{{的值)似乎从未调用过这两个函数1}}和newName不会更改为newNumber(而是保留用户添加的值)。但是,我的其他useState函数(''setPersons())却在setFilteredPersons()内部工作。

我尝试阅读文档并四处询问,但没有找到解决方案。如果有任何提示/帮助,我将不胜感激!

addPerson()

顶部的person组件仅包含以下代码:

import React, { useState } from 'react'
import Person from './components/Person'

const App = () => {
  const [ persons, setPersons ] = useState([
    { name: 'Cat', number: '111' },
    { name: 'Dog', number: '222' },
    { name: 'Horse', number: '333' },
    { name: 'Owl', number: '444' }
  ]) 
  const [filteredPersons, setFilteredPersons] = useState([...persons])
  const [ newName, setNewName ] = useState('')
  const [ newNumber, setNewNumber ] = useState('')

  const addPerson = (event) => {
    event.preventDefault()

    const createPerson = () => {
      const personObject = {
        name: newName,
        number: newNumber,
      }
      setPersons([...persons, personObject])
      setFilteredPersons([...persons, personObject]) //varför går det inte att bara köra [...persons?]
    }

    const upperCaseNewName = newName.toUpperCase()
    let doubleName
    persons.map(person => {
      const upperCasePerson = person.name.toUpperCase()
      if(upperCaseNewName === upperCasePerson) {
        doubleName = upperCasePerson
      }
      return doubleName
    })

    if (doubleName === undefined) {
      createPerson()
    } else if(doubleName === upperCaseNewName) {
      alert(`${newName} is already in the phonebook`)
    }

    setNewName('')
    setNewNumber('')
  }

  const filterEntries = event => {
      let filtered = persons.filter(person => {
        return person.name.toUpperCase().indexOf(event.target.value.toUpperCase()) !== -1
      })
    setFilteredPersons(filtered)
  }

  const renderPersons = () => filteredPersons.map(person =>
    <Person key={person.name} name={person.name} number={person.number}/>
  )

  return (
    <div>
      <h2>Phonebook</h2>
      <p>Filter entries:</p> <input onChange={(event) => filterEntries(event)}/>
      <form>
        <div>
          name: <input onChange={(event) => setNewName(event.target.value)}/>
          <br/>
          phone: <input onChange={(event) => setNewNumber(event.target.value)}/>
        </div>
        <div>
          <button type="submit" onClick={addPerson}>add</button>
        </div>
      </form>
      <h2>Numbers</h2>
      {renderPersons()}
    </div>
  )
}

export default App

3 个答案:

答案 0 :(得分:3)

您的组件实际上并不依赖于您的状态值。您需要对它们进行“控制”。查看文档以获取更多示例:)

https://reactjs.org/docs/forms.html#controlled-components

<input value={newName} onChange={event => setNewName(event.target.value)} />

答案 1 :(得分:2)

重置正常工作。您忘记要做的是将value添加到每个输入中。如果没有value属性,则输入被视为uncontrolled component。听起来,您正在寻找通过代码control的值。

更改

<div>
  name: <input onChange={event => setNewName(event.target.value)} />
  <br />
  phone: <input onChange={event => setNewNumber(event.target.value)} />
</div>

<div>
  name: <input value={newName} onChange={event => setNewName(event.target.value)} />
  <br />
  phone: <input value={newNumber} onChange={event => setNewNumber(event.target.value)} />
</div>

Codesandbox Demo

答案 2 :(得分:1)

您错过了向value添加input属性,因此您的组件不是“受控”组件。

您可以阅读更多here

需要更改

<input
   value={newName}
   onChange={event => setNewName(event.target.value)}
/>
<br />
phone:
<input
   value={newNumber}
   onChange={event => setNewNumber(event.target.value)}
/>

Codesandbox链接:https://codesandbox.io/s/crimson-frog-ecp98

希望这会有所帮助!