Javascript React Redux状态数组变量作为prop传递给子组件(无限循环或空数组)

Javascript React Redux状态数组变量作为prop传递给子组件(无限循环或空数组),javascript,reactjs,redux,state,Javascript,Reactjs,Redux,State,我正在将Redux状态变量集合作为道具传递给PokeList.js, 使用useEffect挂钩设置状态,但如果我将props.collection设置为依赖项 array map函数将props.collection视为空数组,因为我试图 在map函数中注销pokeData,如果删除 收集依赖,它创建了一个无限循环的情况,我可以控制台.log 集合,它首先显示空数组,然后显示正确的数组, 如何正确设置状态 我试过在PokeList.js中发送,结果也是一样的, 还尝试直接初始化cardList

我正在将Redux状态变量集合作为道具传递给PokeList.js, 使用useEffect挂钩设置状态,但如果我将props.collection设置为依赖项 array map函数将props.collection视为空数组,因为我试图 在map函数中注销pokeData,如果删除 收集依赖,它创建了一个无限循环的情况,我可以控制台.log 集合,它首先显示空数组,然后显示正确的数组, 如何正确设置状态

我试过在PokeList.js中发送,结果也是一样的, 还尝试直接初始化cardList=props.collection.map。。。但是 获取未定义的卡片列表, 还尝试使用React.memo并将道具设置为依赖项 也不行

//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);
        }
    };
};
//PokeList.js
从“React”导入React,{useState,useffect};
从“react引导/卡”导入卡;
从“react bootstrap/ListGroup”导入列表组;
const PokeList=(道具)=>{
const[cardList,setCardList]=useState();
console.log(props.collection)
useffect(()=>{
var newCardList=props.collection.map(pokeData=>{
console.log(pokeData)
返回(
{pokeData.Name}
{'Height:'+pokeData.Height}
{'Weight:'+pokeData.Weight}
)})
设置卡片列表(新卡片列表)
},[props.collection])
返回(
{cardList}
)
}
导出默认PokeList;
//Search.js
从“React”导入React,{useffect};
从'react bootstrap'导入{Container};
从'react redux'导入{useDispatch,useSelector};
从“./pokedex/PokeList”导入PokeList;
从“./pokedex/actions/pokedexActions”导入*作为pokedexActions;
常量搜索=()=>{
const dispatch=usedpatch();
useffect(()=>{
调度(pokedexActions.getLimitNames(5))
}[快讯])
const collection=useSelector(state=>state.pokedex.collection);
返回(
搜寻
);
}
导出默认搜索;
//reducer.js
从“../actions/PokedexActions”导入{GET_LIMIT_NAMES};
常量初始状态={
收藏:[]
};
导出默认值(状态=初始状态,操作)=>{
开关(动作类型){
案例获取\u限制\u名称:
返回{
收集:action.data
};
违约:
返回状态;
}
};
//action.js
从“../Pokemon”导入口袋妖怪;
export const GET\u LIMIT\u NAMES=“GET\u LIMIT\u NAMES”;
export const getLimitNames=(limit=100)=>{
//雷迪克斯·图恩
返回异步调度=>{
试一试{
const allResponse=等待获取(`https://pokeapi.co/api/v2/pokemon/?limit=${limit}`);
const allUrlsData=await allResponse.json();
//控制台日志(allUrlsData.results);
常量集合=[];
Promise.all(allUrlsData.results.map)(urlData=>{
口袋妖怪;
获取(urlData.url)。然后(resp=>
resp.json()
)。然后(数据=>{
//控制台日志(数据);
口袋妖怪=新的口袋妖怪(数据);
//pokemon.log();
收藏推送(口袋妖怪)
}).catch(错误=>{
控制台日志(err);
})
回收;
}))
//console.log(集合)
派遣({
类型:获取\u限制\u名称,
数据:收集
});
}捕捉(错误){
控制台日志(err);
}
};
};
如果我尝试直接渲染贴图结果,则没有显示任何内容,贴图函数 仍然只获取空数组

// 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;
//PokeList.js
从“React”导入React;
从“react引导/卡”导入卡;
从“react bootstrap/ListGroup”导入列表组;
导入“./Pokedex.css”
const PokeList=(道具)=>{
console.log('props.collection',props.collection)
返回(
// 
//{cardList}
// 
{props.collection.map(pokeData=>{
返回(
{pokeData.Name}
{“高度:+pokeData.Height}
{“重量:+pokeData.Weight}
);
})}
)
}
导出默认PokeList;

如果删除[props.collection]依赖项,它将创建无限循环 情况,但组件正在渲染
这里的问题是每次
搜索
呈现时,都会创建
集合
,并将其传递给
PokeList
。然后,
PokeList
使用该
collection
(记住,每次渲染都是新的),并将其用作钩子的依赖项。这意味着每次
Search
呈现时,
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>
    );
};

const PokeList=props=>{
console.log(props.collection);
返回(
{props.collection.map(pokeData=>{
返回(
{pokeData.Name}
{“高度:+pokeData.Height}
{“重量:+pokeData.Weight}
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)
            }