[英]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.