简体   繁体   中英

Difficulty updating state to reflect what's in a spliced updated object array

I was wondering if anybody could help, I'm new to ReactJS and am having a difficult time updating state to reflect what's in an updated object array, example below but in short everything works fine until I add splice into the mix, it seems that state isn't excluding what objects I am splicing out of the array, the 'searchResults' variable and even the 'results' state console.log displays the correct updated data but it just isn't showing down in my 'ResultsPage' child component like it should, I just get the original fetch data before the splice.

Any help would be great, thank you in advance.

import { useState, useEffect } from 'react'
import ResultsPage from './components/ResultsPage'

const App = () => {

    const [results, setResults] = useState([])
    const searchedRef = useRef()

    useEffect(() => {
       console.log(results)
    }, [results])

    const handleSearch = async () => {
        let searched = searchedRef.current.value
        let res = await fetch(`someAPI/${searched}`)
        let data = await res.json()
        searchResults = data
        searchResults = searchResults.splice(searchResults.findIndex(element => element.id === '123456') , 1)
        setResults(searchResults)
    }

    return (
        <>
            <input type="text" ref={searchedRef} onKeyDown={handleSearch}/>
            <ResultsPage results={results} />
        </>
    )

}

export default App

Thee return type of splice is not the remaining array after deletion but it is an array of deleted elements. splice mutates the original array so you don't need to reassign the result of splice to the searchResults variable.

The below code will work for you

const handleSearch = async () => {
        let searched = searchedRef.current.value
        let res = await fetch(`someAPI/${searched}`)
        let data = await res.json()
        searchResults = data
        searchResults.splice(searchResults.findIndex(element => element.id === '123456') , 1)
        setResults(searchResults)
    }

The splice method mutates the contents of the array in place and it returns, according to MDN:

An array containing the deleted elements.

The following code is probably what you are after.

searchResults = data;
searchResults.splice(searchResults.findIndex(element => element.id === '123456') , 1);
setResults(searchResults);

Another, non-destructive, method you could use is array.filter :

const filteredResults = searchResults.filter(element => element.id !== '123456');

You can get the same result using Array.prototype.filter() :

searchResults = searchResults.filter(element => element.id !== '123456');

The code is incomplete, so we cannot create a fast sandbox and solve your problem, but you could try passing all the elements of the results array as a string into ResultsPage for a key.

What I mean:

<ResultsPage results={results} key={results.join('_')} />

This would only work if your results are strings. If they are objects, you should first stringify each one of them.

You could also set a new random key each time your useEffect hook is called:

import shortid from 'shortid';

const [randomKey, setRandomKey] = useState(shortid());

useEffect(() => {
    console.log(results);
    setRandomKey(shortid());
}, [results])

<ResultsPage results={results} key={randomKey} />

The code above should be added to the one you've posted. Let me know if your problem is solved.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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