我创建了一个演示示例来帮助解释这个问题。下面我使用来自
usehooks的
useFetch
钩子。
考虑到 Pokemon API,我只想存储从获取请求收到的一些数据。我想将该数据传递给子组件。
更新 setAbilities 和 setName 的正确方法是什么?除了使用
React.useState
和 React.useEffect
之外,还有其他更有益的方法吗?
import * as React from "react"
import { useFetch } from "@uidotdev/usehooks";
const PokemonContext = React.createContext()
export function Demo() {
const { error, data } = useFetch("https://pokeapi.co/api/v2/pokemon/1");
const [abilities, setAbilities] = React.useState(null)
const [name, setName] = React.useState(null)
// ... update with setAbilities and setName
if (error) return <h1>Error...</h1>;
if (!data) return <h1>Loading...</h1>;
return (
<PokemonContext.Provider value={{abilities, name}}>
<Pokemon />
</PokemonContext.Provider>
);
}
function Pokemon () {
const {abilities, name} = React.useContext(PokemonContext)
return (
<div>
<h1>{name}</h1>
<div>
Abilities:
<ul>
{abilities.map((ability, index) => (
<li key={index}>{ability.ability.name}</li>
))}
</ul>
</div>
</div>
);
}
我尝试过使用 React.useEffect,然后使用 setAbilities 和 setName,但我不知道这是否是 React 中处理此问题的正确方法。
编辑:
这就是我解决这个问题的方法。这是最优的吗?
import * as React from "react"
import {useFetch} from "../hooks/useFetch.jsx";
const PokemonContext = React.createContext()
export function Hooks() {
const { error, data } = useFetch("https://pokeapi.co/api/v2/pokemon/1");
const [abilities, setAbilities] = React.useState([])
const [name, setName] = React.useState("")
React.useEffect(() => {
if (data) {
setAbilities(data.abilities)
setName(data.name)
}
}, [data])
if (error) return <h1>Error...</h1>;
if (!data) return <h1>Loading...</h1>;
return (
<PokemonContext.Provider value={{abilities, name}}>
<Pokemon />
</PokemonContext.Provider>
);
}
function Pokemon () {
const {abilities, name} = React.useContext(PokemonContext)
return (
<div>
<h1>{name}</h1>
<div>
Abilities:
<ul>
{abilities.map((ability, index) => (
<li key={index}>{ability.ability.name}</li>
))}
</ul>
</div>
</div>
);
}
您不应该直接渲染能力,而应该渲染一个将能力作为参数的函数,根据需要更改它们并返回更改后的值:
formattedAbilities = (abilities) => {
let formattedAbilities = abilities;
//do whatever you want to the formattedAbilities
return formattedAbilities;
}
function Pokemon () {
const {abilities, name} = React.useContext(PokemonContext)
return (
<div>
<h1>{name}</h1>
<div>
Abilities:
<ul>
{formattedAbilities(abilities).map((ability, index) => (
<li key={index}>{ability.ability.name}</li>
))}
</ul>
</div>
</div>
);
}