我正在学习React和Redux,并创建了一个Pokemon生成器应用程序来学习。我目前正在尝试为现有的口袋妖怪做一个更新表单;然而,它使我意识到我对这些组件工作方式有一个误解。
我有一个PokemonDetailContainer
import { connect } from 'react-redux'
import { requestSinglePokemon } from '../../actions/pokemon_actions'
import { pokemonDetail } from './pokemon_detail'
const mapDispatchToProps = dispatch => ({
requestSinglePokemon: (pokemonId) => dispatch(requestSinglePokemon(pokemonId))
})
const mapStateToProps = (state) => ({
state: state,
loading: state.ui.loading
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(pokemonDetail)
连接到PokemonDetail组件的
import React, { useEffect, useState } from "react";
import { Route, Routes } from "react-router-dom";
import { useParams } from "react-router-dom";
import { selectPokemonMoveNames } from "../../reducers/selectors";
import ItemDetailContainer from '../items/item_detail_container'
import { Item } from "../items/item";
import LoadingIcon from "./loading_icon";
export function pokemonDetail (props) {
const { pokemonId } = useParams({pokemonId})
const items = Object.values(props.state.entities.items)
const moves = selectPokemonMoveNames(props.state)
const thisPokemon = props.state.entities.pokemon[pokemonId]
const [state, setState] = useState()
useEffect(() => {
const pokemon = props.requestSinglePokemon(pokemonId);
}, [])
if (thisPokemon && !props.loading.detailLoading) {
return(
<section className="pokemon-detail">
<Routes>
<Route path="/items/:itemId" element={< ItemDetailContainer />}></Route>
</Routes>
<ul>
<figure>
<img src={thisPokemon.imageUrl} alt={thisPokemon.name} />
</figure>
<li><h2>{thisPokemon.name}</h2></li>
<li>Type: {thisPokemon.pokeType}</li>
<li>Attack: {thisPokemon.attack}</li>
<li>Defense: {thisPokemon.defense}</li>
<li>Moves: {moves.join(', ')}</li>
</ul>
<section className="toys">
<h3>Items</h3>
<ul className="toy-list">
{items.map(item => <Item key={item.name} itemProps={item}/>)}
</ul>
</section>
</section>
)
} else {
return (
<LoadingIcon />
)
}
}
现在,我认为useEffect将允许我分派我的动作-在本例中,从以下动作加载单个口袋妖怪的请求-并通过useState将其分配给状态,但如果我尝试这样做,它会给我一个无限循环(如果在useEffect内完成)或返回空。
export const receiveOnePokemon = payload => ({
type: RECEIVE_ONE_POKEMON,
payload
})
...
export const requestSinglePokemon = (id) => (dispatch) => {
APIUtil.fetchPokemon(id).then(
(payload) => (dispatch(receiveOnePokemon(payload)))
)
}
因此,虽然一切都正常,但当进入口袋妖怪详细信息页面时,整个状态正在重新加载,同时加载了一个口袋妖怪,我不确定如何将单个口袋妖怪信息作为 prop 传递(即,没有整个状态),因为ownProps似乎不再工作。正因为如此,我不知道如何创建一个表单来更新一个口袋妖怪。如果有人能帮助我理解useEffect和mapStateToProps在此上下文中的含义,那将有很大帮助!我一直觉得很迷茫
1条答案
按热度按时间dsekswqp1#
我看了一下,我想我真的可以帮助你。看起来你有一些关于useEffect,mapStateToProps的使用的问题和担忧,以及在React和Redux应用程序中更新单个口袋妖怪。让我们一步一步地解决每个问题:
使用效果和调度动作:在当前的实现中,您正在useEffect钩子中调度requestSinglePokemon操作。但是,您需要确保requestSinglePokemon操作是从操作创建者返回的,以防止无限循环。按如下方式修改代码:
通过移除对const pokemon =...的赋值,可以确保动作被正确分派。
访问单个口袋妖怪作为 prop :要从状态访问单个口袋妖怪并将其作为 prop 传递给组件,您可以修改PokemonDetailContainer中的mapStateToProps函数:
这里,我们从ownProps.match.params中提取pokemonId,从路由参数中获取Pokemon的具体ID。然后,我们从Redux状态中检索相应的Pokemon,并将其作为Pokemon prop 传递给您的组件。
更新单个Pokemon:要创建一个更新单个口袋妖怪的表单,您需要调度一个操作来更新Redux商店中的口袋妖怪信息。首先,创建一个更新口袋妖怪的动作创建器:
在你的组件中,你现在可以定义一个表单,并在提交表单时分派updatePokemon动作:
在handleSubmit函数中,从表单字段中提取更新的数据,并使用pokemonId和updatedData作为参数分派updatePokemon操作。
请记住导入updatePokemon动作创建器并将其包含在mapDispatchToProps函数中。
通过这些更改,您应该能够获取单个口袋妖怪,显示其详细信息,并使用React和Redux应用程序中的表单更新其信息。我真的希望我能帮助你!