我的状态不断将空元素添加到其数组中

发布于 2025-01-22 11:33:09 字数 6801 浏览 0 评论 0原文

对于setperson,我的二传手似乎一直在没有明显的原因中将空元素添加到其数组中。当我更新用户的电话号码时,我正在尝试使我的电话号码列表立即更新,但它坚持使用旧数字。每当我将逻辑应用以立即进行数字更新时,它会将空元素添加到我的数组中,并且不会立即更新。这是每个单独组件的代码:

app.js

import { useEffect, useState, useRef} from 'react'
import PersonForm from './components/PersonForm'
import Display from './components/Display'
import Filter from './components/Filter'
import phoneService from './services/information'

const App = () => {
  const [errorMessage, setErrorMessage] = useState('')
  const [persons, setPersons] = useState('')
  const [newName, setNewName] = useState('')
  const [newNumber, setNewNumber] = useState('')
  const [filter, setFilter] = useState('')
  const [filterChecker, setFilterChecker] = useState('')
  
  useEffect(() => {
    phoneService.getAll()
    .then(people => setPersons(people))
  }, [])

  const handleSubmit = (e) => {
    e.preventDefault();
    const copy = [...persons]
    const foundNameOrNot = persons.some(el => el.name === newName)
    const foundNumberOrNot = persons.some(el => el.number === newNumber)
    const eachPersonsID = persons.map(person => person.id)
    const newObj = {
      name: newName,
      number: newNumber,
      id: Math.max(eachPersonsID) + 1
    }
    if (foundNameOrNot) {
      if(window.confirm(`${newName} is added to phonebook, replace the old number with a new one.`)) {
        const indexFinder = persons.filter(person => person.name === newName)
        newObj.id = indexFinder[0].id
        copy[indexFinder[0].id] = newObj
        phoneService.update(indexFinder[0].id, newObj)
        .then(res => {
          setErrorMessage(`Successfully updated ${newName}s number`)
          setPersons([copy])})
        .catch(err => {
          setErrorMessage(`Information on ${newName} has already been removed`)
          setFilterChecker(filterChecker.filter(filter => filter !== newName))})
      }
    } else if (foundNumberOrNot) {
      alert(`${newNumber} belongs to someone else`)
    } else {
      phoneService.create(newObj).then(res => setPersons([...persons, newObj]))
    }
  }

  const handleFilter = (e) => {
    console.log(persons)
    setFilter(e.target.value)
    const allNames = persons.map(person => person.name)
    setFilterChecker(allNames.filter(name => name.toLowerCase().indexOf(filter.toLowerCase()) !== -1))
  }

  return (
    <div>
      <h1 className='error'>{errorMessage ? errorMessage : ''}</h1>
      <h2>Phonebook</h2>
      <Filter filter={filter} handleFilter={handleFilter}/>
      <h2>add a new</h2>
      <form onSubmit={handleSubmit}>
        <PersonForm newName={newName} newNumber={newNumber} setNewName={setNewName} setNewNumber={setNewNumber}/>
        <div>
          <button type="submit">add</button>
        </div>
      </form>
      <h2>Numbers</h2>
      <Display filterChecker={filterChecker} persons={persons} setPersons={setPersons} setFilterChecker={setFilterChecker} errorMessage={errorMessage} setErrorMessage={setErrorMessage} />
    </div>
  )
}

export default App

display.js

import phoneService from '../services/information'
import axios from 'axios'
import { useState } from 'react'

const handleDelete = (i, persons, setPersons, name2, setFilterChecker, errorMessage, setErrorMessage) => {
    if (window.confirm(`delete ${name2} ?`)) {
        const newArrayOfPeople = persons.filter(person => person.name !== name2)
        const newArrayOfNames = newArrayOfPeople.map(person => person.name)
        setFilterChecker(newArrayOfNames)
        setPersons(newArrayOfPeople)
        phoneService.remove(persons[i].id)
        setErrorMessage(`You have successfully deleted ${name2} from the list.`)
        setTimeout(() => {
            setErrorMessage(null)
        }, 5000)
    }
}

const Display = ({filterChecker, persons, setPersons, setFilterChecker, errorMessage, setErrorMessage}) => {
    const copy = [...persons]
    const findNumbers = []
    const findNames = []
    for (let j = 0; j < copy.length; j++) {
        if (copy[j]?.name && !findNames.includes(copy[j]?.name)) {
            findNames.push(copy[j].name)
        }
    }
    for (let i = 0; i < copy.length; i++) {
        if (copy[i]?.number && !findNumbers.includes(copy[i]?.number)) {
            findNumbers.push(copy[i]?.number)
        }
    }
  if (filterChecker) {
    return (
      findNames.map((name, i) => <div><nobr key={name}>{name} {findNumbers[i]}</nobr> <button onClick={() => handleDelete(i, persons, setPersons, name, setFilterChecker, errorMessage, setErrorMessage)}>delete</button></div>)
      )
  } else {
    return ''
  }

}

export default Display

filter.js

const Filter = ({filter, handleFilter}) => {
    return <p>filter shown with <input value={filter} onChange={handleFilter}/></p>
  }
  
  export default Filter

personform.js

import axios from 'axios';
import phoneService from '../services/information'

const PersonForm = ({newName, newNumber, setNewName, setNewNumber}) => {

  return (
    <div>
      name: <input value={newName} onChange={(e) => setNewName(e.target.value)}/>
      number: <input value={newNumber} onChange={(e) => setNewNumber(e.target.value)}/>
    </div>
  )
}

export default PersonForm

inovy.js

import axios from "axios"
const baseUrl = 'http://localhost:3002/numbers'

const getAll = () => {
  const request = axios.get(baseUrl)

  return request.then(response => response.data)
}

const create = newObject => {
  const request = axios.post(baseUrl, newObject)
  return request.then(response => response.data)
}

const update = (id, newObject) => {
  const request = axios.put(`${baseUrl}/${id}`, newObject)
  return request.then(response => response.data)
}

const remove = (id) => {
  const request = axios.delete(`${baseUrl}/${id}`)
  return request.then(res => res.data)
}

export default { getAll, create, update, remove, baseUrl }

我的json服务器“ db.json”,

{
  "numbers": [
    {
      "name": "uvaldo",
      "number": "20",
      "id": 6
    },
    {
      "name": "uvaldo zumaya",
      "number": "24",
      "id": 7
    },
    {
      "name": "uvaldo zumaya d",
      "number": "26",
      "id": 8
    }
  ]
}

每当我尝试更新“ uvaldo”电话号码到22 21然后引发错误,此图片是在我点击“添加”之前以避免程序崩溃...

https:https:https:https: //i.sstatic.net/cd2rh.png

My setter, for SetPersons, seems to keep adding empty elements into its array for no apparent reason. I am trying to make my phone number list update instantaneously when I update a user's number but it sticks with the old number. Whenever I apply the logic to possibly make the number update instantly, it adds empty elements into my array instead and does not update instantly. Here is the code for each separate component:

App.js

import { useEffect, useState, useRef} from 'react'
import PersonForm from './components/PersonForm'
import Display from './components/Display'
import Filter from './components/Filter'
import phoneService from './services/information'

const App = () => {
  const [errorMessage, setErrorMessage] = useState('')
  const [persons, setPersons] = useState('')
  const [newName, setNewName] = useState('')
  const [newNumber, setNewNumber] = useState('')
  const [filter, setFilter] = useState('')
  const [filterChecker, setFilterChecker] = useState('')
  
  useEffect(() => {
    phoneService.getAll()
    .then(people => setPersons(people))
  }, [])

  const handleSubmit = (e) => {
    e.preventDefault();
    const copy = [...persons]
    const foundNameOrNot = persons.some(el => el.name === newName)
    const foundNumberOrNot = persons.some(el => el.number === newNumber)
    const eachPersonsID = persons.map(person => person.id)
    const newObj = {
      name: newName,
      number: newNumber,
      id: Math.max(eachPersonsID) + 1
    }
    if (foundNameOrNot) {
      if(window.confirm(`${newName} is added to phonebook, replace the old number with a new one.`)) {
        const indexFinder = persons.filter(person => person.name === newName)
        newObj.id = indexFinder[0].id
        copy[indexFinder[0].id] = newObj
        phoneService.update(indexFinder[0].id, newObj)
        .then(res => {
          setErrorMessage(`Successfully updated ${newName}s number`)
          setPersons([copy])})
        .catch(err => {
          setErrorMessage(`Information on ${newName} has already been removed`)
          setFilterChecker(filterChecker.filter(filter => filter !== newName))})
      }
    } else if (foundNumberOrNot) {
      alert(`${newNumber} belongs to someone else`)
    } else {
      phoneService.create(newObj).then(res => setPersons([...persons, newObj]))
    }
  }

  const handleFilter = (e) => {
    console.log(persons)
    setFilter(e.target.value)
    const allNames = persons.map(person => person.name)
    setFilterChecker(allNames.filter(name => name.toLowerCase().indexOf(filter.toLowerCase()) !== -1))
  }

  return (
    <div>
      <h1 className='error'>{errorMessage ? errorMessage : ''}</h1>
      <h2>Phonebook</h2>
      <Filter filter={filter} handleFilter={handleFilter}/>
      <h2>add a new</h2>
      <form onSubmit={handleSubmit}>
        <PersonForm newName={newName} newNumber={newNumber} setNewName={setNewName} setNewNumber={setNewNumber}/>
        <div>
          <button type="submit">add</button>
        </div>
      </form>
      <h2>Numbers</h2>
      <Display filterChecker={filterChecker} persons={persons} setPersons={setPersons} setFilterChecker={setFilterChecker} errorMessage={errorMessage} setErrorMessage={setErrorMessage} />
    </div>
  )
}

export default App

Display.js

import phoneService from '../services/information'
import axios from 'axios'
import { useState } from 'react'

const handleDelete = (i, persons, setPersons, name2, setFilterChecker, errorMessage, setErrorMessage) => {
    if (window.confirm(`delete ${name2} ?`)) {
        const newArrayOfPeople = persons.filter(person => person.name !== name2)
        const newArrayOfNames = newArrayOfPeople.map(person => person.name)
        setFilterChecker(newArrayOfNames)
        setPersons(newArrayOfPeople)
        phoneService.remove(persons[i].id)
        setErrorMessage(`You have successfully deleted ${name2} from the list.`)
        setTimeout(() => {
            setErrorMessage(null)
        }, 5000)
    }
}

const Display = ({filterChecker, persons, setPersons, setFilterChecker, errorMessage, setErrorMessage}) => {
    const copy = [...persons]
    const findNumbers = []
    const findNames = []
    for (let j = 0; j < copy.length; j++) {
        if (copy[j]?.name && !findNames.includes(copy[j]?.name)) {
            findNames.push(copy[j].name)
        }
    }
    for (let i = 0; i < copy.length; i++) {
        if (copy[i]?.number && !findNumbers.includes(copy[i]?.number)) {
            findNumbers.push(copy[i]?.number)
        }
    }
  if (filterChecker) {
    return (
      findNames.map((name, i) => <div><nobr key={name}>{name} {findNumbers[i]}</nobr> <button onClick={() => handleDelete(i, persons, setPersons, name, setFilterChecker, errorMessage, setErrorMessage)}>delete</button></div>)
      )
  } else {
    return ''
  }

}

export default Display

Filter.js

const Filter = ({filter, handleFilter}) => {
    return <p>filter shown with <input value={filter} onChange={handleFilter}/></p>
  }
  
  export default Filter

PersonForm.js

import axios from 'axios';
import phoneService from '../services/information'

const PersonForm = ({newName, newNumber, setNewName, setNewNumber}) => {

  return (
    <div>
      name: <input value={newName} onChange={(e) => setNewName(e.target.value)}/>
      number: <input value={newNumber} onChange={(e) => setNewNumber(e.target.value)}/>
    </div>
  )
}

export default PersonForm

information.js

import axios from "axios"
const baseUrl = 'http://localhost:3002/numbers'

const getAll = () => {
  const request = axios.get(baseUrl)

  return request.then(response => response.data)
}

const create = newObject => {
  const request = axios.post(baseUrl, newObject)
  return request.then(response => response.data)
}

const update = (id, newObject) => {
  const request = axios.put(`${baseUrl}/${id}`, newObject)
  return request.then(response => response.data)
}

const remove = (id) => {
  const request = axios.delete(`${baseUrl}/${id}`)
  return request.then(res => res.data)
}

export default { getAll, create, update, remove, baseUrl }

My json-server "db.json"

{
  "numbers": [
    {
      "name": "uvaldo",
      "number": "20",
      "id": 6
    },
    {
      "name": "uvaldo zumaya",
      "number": "24",
      "id": 7
    },
    {
      "name": "uvaldo zumaya d",
      "number": "26",
      "id": 8
    }
  ]
}

Whenever I try to update "uvaldo" phone number to 22, it just stays at 21 then throws errors, this picture is before I hit "add" to avoid the program crashing...

https://i.sstatic.net/CD2rh.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

东北女汉子 2025-01-29 11:33:09

逻辑存在一些问题,您可以在其中更新persons

试试看:

  const handleSubmit = (e) => {
...
        const indexFinder = persons.findIndex(person => person.name === newName)
        newObj.id = persons[indexFinder].id
        copy[indexFinder] = newObj
        phoneService.update(persons[indexFinder].id, newObj)
        .then(res => {
          setErrorMessage(`Successfully updated ${newName}s number`)
          setPersons(copy)})
...
  }

添加空元素的原因是用于放置newObj的索引大于数组的大小:

copy[indexFinder[0].id] = newObj

另请注意,person.id dik不一定意味着它们在数组Persons的索引中。

There are issues with the logic where you update persons.

Try this instead:

  const handleSubmit = (e) => {
...
        const indexFinder = persons.findIndex(person => person.name === newName)
        newObj.id = persons[indexFinder].id
        copy[indexFinder] = newObj
        phoneService.update(persons[indexFinder].id, newObj)
        .then(res => {
          setErrorMessage(`Successfully updated ${newName}s number`)
          setPersons(copy)})
...
  }

The reason why it was adding empty elements is that the index used to place newObj was greater than the size of the array:

copy[indexFinder[0].id] = newObj

Also note that person.id does not necessarily mean that they are in that index of the array persons.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文