【问题标题】:Updating state with setSate in array使用数组中的 usestate 更新状态
【发布时间】:2022-01-09 01:49:21
【问题描述】:

我正在尝试更新 setState 以便在 capturePokemon 数组中包含 ['bulbasaur', 'ivisaur', ...] 和所有点击的 pokemon,但到目前为止我只能设法改变同一个数组?从 console.log 中,如果我点击不同的口袋妖怪,我只会在 capturePkm 数组中得到点击的口袋妖怪。我做错了什么?

import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import PokemonIcon from './PokemonIcon';

const PokemonCard = (props) => {
    const { url } = props
    const URL = url
    const [pokemonCard, setPokemonCard] = useState([])
    const [capturedPkm, setCapturedPkm] = useState([])
    const [notCapturedPkm, setNotCapturedPkm] = useState([])
    const [label, setLabel] = useState('Not captured')

    const toggleCaptured = (checked, id) => {
        const currentChecked = [...capturedPkm];
        if (checked) {
            currentChecked.push(pokemonCard.name)
            console.log(currentChecked)

            setLabel('Captured!')

        } else {
            setLabel('Not captured!')

        }

        setCapturedPkm([...capturedPkm, currentChecked]);
        console.log('captured', capturedPkm,)

    }

    const fetchingPokemonCard = async () => {
        const res = await fetch(URL);
        const data = await res.json();
        //console.log(data)
        setPokemonCard(data)
    }

    useEffect(() => {
        fetchingPokemonCard()
    }, [URL])

    return (
        <>
            <div className='pokemon-card' style={{
                height: '250px',
                maxWidth: '250px',
                margin: '1rem',
                boxShadow: '5px 5px 5px 4px rgba(0, 0, 0, 0.3)',
                cursor: 'pointer',
            }} >
                <Link
                    to={{ pathname: `/pokemon/${pokemonCard.id}` }}
                    state={{ pokemon: pokemonCard, capturedPkm }}
                    style={{ textDecoration: 'none', color: '#000000' }}>
                    <div
                        style={{ padding: '20px', display: 'flex', justifyContent: 'center', alignItems: 'center' }} >
                        <PokemonIcon img={pokemonCard.sprites?.['front_default']} />
                    </div>
                </Link>
                <div style={{ textAlign: 'center' }}>
                    <h1 >{pokemonCard.name}</h1>
                    <label >
                        <input
                            type='checkbox'
                            defaultChecked={false}
                            onChange={(e) => toggleCaptured(e.target.checked, pokemonCard.id)}
                        />
                        <span style={{ marginLeft: 8, cursor: 'pointer' }}>
                            {label}
                        </span>
                    </label>
                </div>
            </div>
            <div>
            </div>
        </>
    )
}

export default PokemonCard

【问题讨论】:

  • 在更新capturedPkm的状态时,你必须在设置标签之前使用setCapturedPkm
  • 所以我必须在设置标签之前移动这一行? setCapturedPkm([...capturedPkm, currentChecked]);

标签: arrays reactjs event-handling setstate


【解决方案1】:
import React, { useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import PokemonIcon from './PokemonIcon';

const PokemonCard = (props) => {
    const { url } = props
    const URL = url
    const [pokemonCard, setPokemonCard] = useState([])
    const [capturedPkm, setCapturedPkm] = useState([])
    const [notCapturedPkm, setNotCapturedPkm] = useState([])
    const [label, setLabel] = useState('Not captured')

    const toggleCaptured = (checked, id) => {
        setCapturedPkm(prevState => {
            const newChecked = [...prevState];
            if (checked) {
                newChecked.push(pokemonCard.name)
                console.log(currentChecked)
                setLabel('Captured!')
    
            } else {
                setLabel('Not captured!')
            }
            return newChecked;
        });
    }

    useEffect(() => {
        console.log('captured', capturedPkm,)
    }, [capturedPkm])

    const fetchingPokemonCard = async () => {
        const res = await fetch(URL);
        const data = await res.json();
        //console.log(data)
        setPokemonCard(data)
    }

    useEffect(() => {
        fetchingPokemonCard()
    }, [URL])

    return (
        <>
            <div className='pokemon-card' style={{
                height: '250px',
                maxWidth: '250px',
                margin: '1rem',
                boxShadow: '5px 5px 5px 4px rgba(0, 0, 0, 0.3)',
                cursor: 'pointer',
            }} >
                <Link
                    to={{ pathname: `/pokemon/${pokemonCard.id}` }}
                    state={{ pokemon: pokemonCard, capturedPkm }}
                    style={{ textDecoration: 'none', color: '#000000' }}>
                    <div
                        style={{ padding: '20px', display: 'flex', justifyContent: 'center', alignItems: 'center' }} >
                        <PokemonIcon img={pokemonCard.sprites?.['front_default']} />
                    </div>
                </Link>
                <div style={{ textAlign: 'center' }}>
                    <h1 >{pokemonCard.name}</h1>
                    <label >
                        <input
                            type='checkbox'
                            defaultChecked={false}
                            onChange={(e) => toggleCaptured(e.target.checked, pokemonCard.id)}
                        />
                        <span style={{ marginLeft: 8, cursor: 'pointer' }}>
                            {label}
                        </span>
                    </label>
                </div>
            </div>
            <div>
            </div>
        </>
    )
}

export default PokemonCard

【讨论】:

  • 非常感谢。为什么你在 useEffect 中 console.log 数组?
  • 因为 setState 是异步操作,如果你 console.log 后的状态 setState 可能 javascript 仍然显示旧的状态值
  • 即使这样,我刚刚检查了您的解决方案,我仍然只得到最新的值:/
  • 阅读此链接:v5.reactrouter.com/web/api/Link。您错误地使用了链接。
  • 抱歉,这与我的问题有什么关系?
猜你喜欢
  • 1970-01-01
  • 2021-12-14
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
  • 2019-10-17
相关资源
最近更新 更多