【问题标题】:How am I using React hooks wrong here?我在这里如何使用错误的 React 钩子?
【发布时间】:2020-01-11 16:59:45
【问题描述】:

我正在构建一个简单的电话簿来配合赫尔辛基大学的 FullstackOpen 课程。下面代码中的日志显示我的“filterBy”状态始终是一个渲染,而且我的contacts.filter也收到错误,即“contact.name.toUpperCase”不是一个函数。所以我想我有两个问题。

  1. 我什至可以在不使用类组件的情况下做他们想让我做的事情吗?他们还没有在课程中介绍它们,所以我假设是的。但是我想我曾经在教程中听说过,当您需要状态同步时必须使用类组件(例如,使用输入来过滤屏幕上显示的对象数组)。但我无法让 filterBy 状态实际上与过滤器输入中的内容同步。

  2. 我知道我的行以“const contactsToShow ...”开头可能是一种不太理想的方式来做到这一点,如果有功能的话。怎样才能做到最好?

代码:

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

const App = () => {
  const [contacts, setContacts] = useState([
    { name:'Guy Fieri', number: '020-4837473'},
    { name:'Gordon Ramsay', number: '75749483832'},
    { name:'Mr. Tasty', number: '43-4982839'},
    { name:'Dude man', number: '11-33-448382'},
  ]) 
  const [newName, setNewName] = useState('')
  const [newNumber, setNewNumber] = useState('')
  const [showAll, setShowAll] = useState(true)
  const [filterBy, setFilterBy] = useState('');

  const contactsToShow = showAll ? contacts : contacts.filter(contact => contact.name.toUpperCase().search(filterBy) !== -1)


  const rows = () => contactsToShow.map(contact =>
    <Contact
      key={contact.name}
      name={contact.name}
      number={contact.number}
    />
  )
  
  const handleContactNameChange = (event) => {
    console.log(event.target.value)
    setNewName(event.target.value)
  }

  const handleContactNumberChange = (event) => {
    console.log(event.target.value)
    setNewNumber(event.target.value)
    console.log(newNumber);
  }

  const handleFiltering = (event) => {
    console.log(event.target.value)
    setFilterBy(event.target.value)
    setShowAll(false)
    console.log(filterBy);
  }

  const addContact = (event) => {
    event.preventDefault()
    // 
    if(newName === '') return true
    if(newNumber === '') return true

    let dup = false
    contacts.forEach(contact => {
      if (contact.name === newName) dup = true
    })

    if (!dup) {
      const contactObject = {
        name: newName,
        number: newNumber
      }
  
      setContacts(contacts.concat(contactObject))
      setNewName('')
      setNewNumber('')
    }
  }

  return (
    <div>
      <h1>Phonebook</h1>
      <form onSubmit={addContact}>
      <div>
        Filter:<input value={filterBy} onChange={handleFiltering}/>
      </div>
        Name: <input
          value={newName} 
          onChange={handleContactNameChange}
        /><br/>
        Number: <input
          value={newNumber} 
          onChange={handleContactNumberChange}
        /><br/>
        <button type="submit">save</button>
      </form>
      <ul>
        {rows()}
      </ul>
    </div>
  )
}

export default App 

我可以尝试什么?我对这样的 React 很陌生。

【问题讨论】:

  • 你可以在不使用课程的情况下做到这一点,但我会在你的作业中看到他们想要什么。而且我认为您的 filter 方法设置错误,这就是您收到 ToUpperCase 错误的原因
  • @mph85 是的,他们并没有为此提供进一步的说明或解决方案。这只是学校提供的在线课程。他们还没有引入类组件,所以我现在很难过。
  • 问题是你忘了把contactsToShow 变成一个函数。使用const contactsToShow = () =&gt; showAll ...const rows = () =&gt; contactsToShow().map(... 就可以了:codesandbox.io/s/divine-cloud-vv3ob
  • @ChrisG 谢谢!如果您想提交作为答案,我很乐意接受并给您代表。如果可以的话,你介意解释一下为什么在这种情况下需要一个函数吗?我有另一个用例,我使用过滤器只显示“重要”注释,但这是一个布尔字段,并且在没有它的情况下工作。
  • 抱歉,我跑题了;您的代码中唯一的“问题”是您没有使用filterBy.toUpperCase();我修复了我的沙箱。日志记录滞后,因为设置状态是异步的。

标签: javascript reactjs react-hooks


【解决方案1】:

您的代码需要进行一些更改。我不明白您为什么会收到此错误contact.name.toUpperCase,因为这没有任何问题。

您正在将contact 转换为大写,但不是filterBy

现在,回答你的两个问题:

  1. 您正在使用 react 16 中引入的钩子。这为功能组件带来了状态。您的代码可以与钩子或类组件一起正常工作。

  2. 每当您更改任何状态变量 (contact, newName, newNumber, showAll, filterBy) 时,您的组件都会重新渲染。这将调用rows() 函数并显示您想要的结果。所以你可以在函数内推contactsToShow

您的代码没有任何问题。我不知道Contact 组件是什么,所以我将其更改为div 并添加了一个console.log 以查看发生了什么。它运行良好。看看这个: https://codesandbox.io/embed/vibrant-dawn-o1r1y

如果您有更多疑问,可以告诉我,我随时为您提供帮助。 :)

【讨论】:

  • Array.concat 返回一个新数组,所以可以使用;它不会变异contacts
  • 所以我有点困惑。通过在我的 filterBy 状态上调用 toUpperCase 也修复了过滤功能。函数不存在错误是由早期的 .toUpperCase 引起的,我没有用 () 调用,所以 JS 在那里寻找一个属性。我想我在发布代码之前已经解决了这个问题。感谢您的帮助!
  • 因为您在执行 .toUpperCase() 时将“Gordon Ramsay”转换为“GORDON RAMSAY”,但当过滤器为“gordon”时,它不会过滤。因此,您需要对名称和过滤器执行 toUpperCase() 或 toLowerCase()。
  • 酷。祝你好运! :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
  • 2023-01-04
  • 1970-01-01
  • 2021-09-29
  • 2020-02-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多