简体   繁体   English

我在这里如何错误地使用 React 钩子?

[英]How am I using React hooks wrong here?

I'm building a simple Phonebook to go along with FullstackOpen course from University of Helsinki.我正在构建一个简单的电话簿,以配合赫尔辛基大学的 FullstackOpen 课程。 My logs from the below code show me that my 'filterBy' state is always a render behind and I'm also getting errors from my contacts.filter that "contact.name.toUpperCase" is not a function.我来自以下代码的日志显示我的“filterBy”状态始终是渲染落后,并且我也从我的contacts.filter 中收到错误,即“contact.name.toUpperCase”不是一个函数。 So i guess I have 2 questions.所以我想我有两个问题。

  1. Can I even do what they're trying to have me do without using class components?我什至可以在不使用类组件的情况下做他们想让我做的事情吗? They haven't introduced them in the course yet, so I'm assuming yes.他们还没有在课程中介绍它们,所以我假设是的。 But I thought I heard in a tutorial once that class components have to be used when you need state to be in sync (eg using an input to filter an array of objects displayed on screen).但是我想我曾经在一个教程中听说过当您需要状态同步时必须使用类组件(例如,使用输入来过滤屏幕上显示的对象数组)。 But I can't get the filterBy state to actually be in sync with what's in the filter input.但是我无法让 filterBy 状态与过滤器输入中的内容实际同步。

  2. I know my line starting "const contactsToShow . . ."我知道我的行开始是“const contactsToShow ..” is probably a less than optimal way to do it, if functional at all.如果有功能的话,这可能是一种不太理想的方法。 How can this best be done?如何做到最好?

Code:代码:

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 

What can I try?我可以尝试什么? I'm very new to React like this.我对这样的 React 很陌生。

There are some changes needed in your code.您的代码需要进行一些更改。 I don't see why you are even getting this error contact.name.toUpperCase because there is nothing wrong with that.我不明白为什么您甚至会收到此错误contact.name.toUpperCase因为这没有任何问题。

You are converting the contact to upperCase but not filterBy .您正在将contact转换为 upperCase 而不是filterBy

Now, to answer your two questions:现在,回答你的两个问题:

  1. You are using hooks that were introduced with react 16. This brought state to functional components.您正在使用 react 16 引入的钩子。这为功能组件带来了状态。 Your code will work fine with hooks or class component.您的代码可以与钩子或类组件一起正常工作。

  2. Whenever you make a change in any state variable ( contact, newName, newNumber, showAll, filterBy ), your component re-renders.每当您更改任何状态变量( contact, newName, newNumber, showAll, filterBy )时,您的组件都会重新渲染。 This will call the rows() function and display the result that you want.这将调用rows()函数并显示您想要的结果。 So you can just push contactsToShow inside the function.所以你可以只在函数内部推送contactsToShow

There is nothing breaking with your code.您的代码没有任何问题。 I don't know what Contact component was, so I changed it to div and added a console.log to see what's happening.我不知道Contact组件是什么,所以我将其更改为div并添加了一个 console.log 以查看发生了什么。 It runs fine.它运行良好。 Check it out: https://codesandbox.io/embed/vibrant-dawn-o1r1y检查一下: https : //codesandbox.io/embed/vibrant-dawn-o1r1y

You can let me know if you have more doubts, I'm here to help.如果您有更多疑问,可以告诉我,我会在这里提供帮助。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM