React hooks: Невозможно обновить состояние внутри компонента функции - PullRequest
1 голос
/ 15 октября 2019

Я новичок в React и пытаюсь выяснить, как сделать телефонную книгу. Я довольно далеко, но у меня проблема, которую я не могу решить. Я использую React Hooks.

Все работает нормально, за исключением случаев, когда я вызываю функции setNewNumber('') и setNewName('') в конце addPerson(), непосредственно перед константой filteredEntries. Я хочу сбросить поля ввода в форме на пустые строки (''), как только другой код внутри addPerson() будет выполнен, но кажется, что две функции никогда не вызываются, так как значение для newName и newNumber не изменяйте на '' (вместо этого они сохраняют значения, добавленные пользователем). Однако другие мои функции useState (setPersons() и setFilteredPersons()) работают внутри addPerson() ...

Я пытался прочитать документацию и задать вопрос, но не нашел решения. Я был бы очень признателен за любые подсказки / помощь!

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

Компонент person вверху просто содержит этот код:

import React from 'react'

const Person = (props) => {
    return(
        <>
        <p>{props.name} {props.number}</p>
        </>
    )
}

export default Person

Ответы [ 3 ]

3 голосов
/ 15 октября 2019

Ваши компоненты фактически не привязаны к вашим значениям состояния. Вы должны их контролировать. Проверьте документы для большего количества примеров:)

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

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

2 голосов
/ 15 октября 2019

Сброс работает правильно. То, что вы забыли сделать, это добавить value к каждому входу. Без атрибута value вход считается неуправляемым компонентом . Судя по звукам, вам нужно контролировать значение с помощью кода.

Изменить

<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

1 голос
/ 15 октября 2019

Вы пропустили добавление атрибута value к input, и, таким образом, ваш компонент не является "контролируемым" компонентом.

Вы можете прочитать больше здесь .

Необходимые изменения

<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

Надеюсь, это поможет!

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