代码之家  ›  专栏  ›  技术社区  ›  Mike Waldrup

我怎么用反作用钩子错了?

  •  2
  • Mike Waldrup  · 技术社区  · 5 年前

    我正在建立一个简单的电话簿,与赫尔辛基大学的fullstackopen课程一起使用。下面代码中的日志告诉我,我的“filterby”状态总是呈现在后面,而且我还从contacts.filter中得到错误,即“contact.name.touppercase”不是函数。所以我想我有两个问题。

    1)我甚至可以在不使用类组件的情况下做他们想让我做的事情吗?他们还没有在课程中介绍他们,所以我想是的。但我想我在一个教程中听说过,当需要状态同步时,必须使用类组件(例如,使用输入过滤屏幕上显示的对象数组)。但我不能让filterby状态与filter输入中的内容同步。

    2)我知道我的线路以“const contactstoshow”开头。..“可能是一个不太理想的方法来做这件事,如果有功能的话。怎样才能做到最好? 如果下面的代码要点不适合阅读: https://gist.github.com/waldrupm/98b39ecc1c31f65e0cc418e9e9964c41

    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 
    

    有什么建议吗?我在这里已经没有办法了,我对这样的反应还很陌生。谢谢您!

    1 回复  |  直到 5 年前
        1
  •  3
  •   Praneeth Paruchuri    5 年前

    您的代码中需要进行一些更改。我不明白你为什么会犯这个错误 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

    如果你有更多疑问可以告诉我,我是来帮忙的。:)