简体   繁体   English

React Redux state 数组变量作为道具传递给子组件,无限循环或空数组

[英]React Redux state array variable pass as prop to child component, either infinite loop or empty array

I am passing Redux state variable collection as props to PokeList.js, using the useEffect hook to set state, but if I set props.collection as dependency the array map function sees the props.collection as empty array, since I tried to log out pokeData in the map function and gets nothing, if I remove the props.collection dependency, it creates an infinite loop situation, I can console.log the props.collection, which shows an empty array first, then the correct array, how do I set the state correctly? I am passing Redux state variable collection as props to PokeList.js, using the useEffect hook to set state, but if I set props.collection as dependency the array map function sees the props.collection as empty array, since I tried to log out在 map function 中的 pokeData 并没有得到任何东西,如果我删除 props.collection 依赖,它会创建一个无限循环的情况,我可以控制台记录 props.collection,它首先显示一个空数组,然后是正确的数组,我该怎么做正确设置 state?

I have tried dispatching in PokeList.js, which has the same result, also tried dirrectly initialize cardList = props.collection.map... but get cardList undefined, also tried using React.memo and set props as dependency doesn't work either我尝试在 PokeList.js 中进行调度,结果相同,还尝试直接初始化 cardList = props.collection.map... 但未定义 cardList,也尝试使用 React.memo 并将 props 设置为依赖项也不起作用

//PokeList.js
import React, { useState, useEffect } from 'react';
import Card from 'react-bootstrap/Card';
import ListGroup from 'react-bootstrap/ListGroup';

const PokeList = (props) => {
    const [cardList, setCardList] = useState();
    console.log(props.collection)

    useEffect(() => {
        var newCardList = props.collection.map(pokeData => { 
            console.log(pokeData)
            return (
                <Card key={pokeData.id} style={{ width: '18rem' }}>
                    <Card.Img variant="top" src={pokeData.sprite} />
                    <Card.Body>
                        <Card.Title>{pokeData.Name}</Card.Title>
                        <ListGroup className="list-group-flush">
                            <ListGroup.Item>{'Height: ' + pokeData.height}</ListGroup.Item>
                            <ListGroup.Item>{'Weight: ' + pokeData.weight}</ListGroup.Item>
                        </ListGroup>
                    </Card.Body>
                </Card>
            )})
        setCardList(newCardList)
    }, [props.collection])

    return (
        <div>
           {cardList}
        </div>
    )
}

export default PokeList;

//Search.js
import React, { useEffect } from 'react';
import { Container } from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';

import PokeList from './pokedex/PokeList';
import * as pokedexActions from './pokedex/actions/PokedexActions';

const Search = () => {
    const dispatch = useDispatch();

    useEffect(() => {
        dispatch(pokedexActions.getLimitNames(5))
    }, [dispatch])

    const collection = useSelector(state => state.pokedex.collection);

    return (
        <div>
            <Container>
                <h2>Search</h2>
                <PokeList collection={collection}/>
            </Container>
        </div>
    );
}

export default Search;

// reducer.js
import { GET_LIMIT_NAMES } from '../actions/PokedexActions';

const initialState = {
    collection: []
};

export default (state = initialState, action) => {
    switch (action.type) {
        case GET_LIMIT_NAMES:
            return {
                collection: action.data
            };
        default:
            return state;
    }
};
// action.js
import Pokemon from '../Pokemon';

export const GET_LIMIT_NAMES = "GET_LIMIT_NAMES";

export const getLimitNames = (limit = 100) => {
    // redux-thunk
    return async dispatch => {
        try {
            const allResponse = await fetch(`https://pokeapi.co/api/v2/pokemon/?limit=${limit}`);
            const allUrlsData = await allResponse.json();
            // console.log(allUrlsData.results);

            const collection = [];

            Promise.all(allUrlsData.results.map(urlData => {
                var pokemon;
                fetch(urlData.url).then(resp =>
                    resp.json()
                ).then(data => {
                    // console.log(data);
                    pokemon = new Pokemon(data);
                    // pokemon.log();
                    collection.push(pokemon)
                }).catch(err => {
                    console.log(err);
                })
                return collection;
            }))

            // console.log(collection)

            dispatch({
                type: GET_LIMIT_NAMES,
                data: collection
            });

        } catch (err) {
            console.log(err);
        }
    };
};

if I try to directly render the map result, nothing appeared, the map function still only gets the empty array,如果我尝试直接渲染 map 结果,什么也没有出现, map function 仍然只得到空数组,

// PokeList.js
import React from 'react';
import Card from 'react-bootstrap/Card';
import ListGroup from 'react-bootstrap/ListGroup';
import './Pokedex.css'

const PokeList = (props) => {
    console.log('props.collection', props.collection)

    return (
        // <div className='poke-list'>
        //    {cardList}
        // </div>
        <div className='poke-list'>
            {props.collection.map(pokeData => {
                return (
                    <Card key={pokeData.id} style={{ width: "18rem" }}>
                        <Card.Img variant="top" src={pokeData.sprite} />
                        <Card.Body>
                            <Card.Title>{pokeData.Name}</Card.Title>
                            <ListGroup className="list-group-flush">
                                <ListGroup.Item>{"Height: " + pokeData.height}</ListGroup.Item>
                                <ListGroup.Item>{"Weight: " + pokeData.weight}</ListGroup.Item>
                            </ListGroup>
                        </Card.Body>
                    </Card>
                );
            })}
        </div>
    )
}

export default PokeList;

在此处输入图像描述

if I remove the [props.collection] dependency, it creates the infinite loop situation, but the components are rendering如果我删除 [props.collection] 依赖项,它会创建无限循环情况,但组件正在渲染在此处输入图像描述

The issue here is that every time Search renders, collection is created and passed to PokeList .这里的问题是,每次Search呈现时,都会创建collection并将其传递给PokeList Then PokeList is using that collection (new on every render, remember) and using it as a dependency of your hook.然后PokeList正在使用该collection (记住,每次渲染都是新的)并将其用作钩子的依赖项。 This means that every time Search renders, the hook in PokeList will run.这意味着每次Search渲染时, PokeList中的钩子都会运行。

Simply use collection prop to render the Component tree inside PokeList :只需使用collection prop 来渲染PokeList中的组件树:

const PokeList = props => {
    console.log(props.collection);

    return (
        <div>
            {props.collection.map(pokeData => {
                return (
                    <Card key={pokeData.id} style={{ width: "18rem" }}>
                        <Card.Img variant="top" src={pokeData.sprite} />
                        <Card.Body>
                            <Card.Title>{pokeData.Name}</Card.Title>
                            <ListGroup className="list-group-flush">
                                <ListGroup.Item>{"Height: " + pokeData.height}</ListGroup.Item>
                                <ListGroup.Item>{"Weight: " + pokeData.weight}</ListGroup.Item>
                            </ListGroup>
                        </Card.Body>
                    </Card>
                );
            })}
        </div>
    );
};

turns out the problem is in Acions.js Problem.all by changing into for loop and await for all fetches solves the not empty array problem原来问题出在 Acions.js Problem.all 通过更改为 for 循环并等待所有获取解决了非空数组问题

for (var i=0; i<allUrlsData.results.length; i++) {
                const res = await fetch(allUrlsData.results[i].url)
                const resData = await res.json()
                const pokemon = new Pokemon(resData)
                collection.push(pokemon)
            }

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

相关问题 React-Redux:连接到状态数组时的无限循环? - React-Redux: Infinite loop when concat to an array in state? React传递prop到其他组件以从状态数组中删除 - React pass prop to other component to delete from state array 在反应中传递状态或道具以将值传递给子组件 - Passing a state or prop to pass a value to child component in react React.js如何从this.props数组中将index作为prop传递给子组件 - React.js how to pass in index as prop to child component from this.props array React useEffect 无限循环,尽管数组为空 - React useEffect infinite loop despite empty array 如何将prop传递给可变长度的子级数组中的子级组件? - How can I pass a prop to a child component, in a variable length array of children? 反应:无法访问状态变量的值,并且数组或迭代器中的每个子代都应具有唯一的“键”属性 - React: Not able to access the value of state variable and each child in an array or iterator should have a unique “key” prop 反应设置 state 到子组件导致无限循环 - React setting state to child component causing infinite loop Reactjs 子组件在设置时进入无限循环 state 父组件在 props 中提供的数组 - Reactjs child component goes into infinite loop on setting state array provided by parent in props 组件中的空状态(对redux的反应) - Empty state in component ( react redux )
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM