在我的 React 游戏中,我使用名为 Formik 的 React 库作为表单。
在其中,您可以像这样设置表单的初始值:
<Formik
initialValues={{
characterClasses: ["1", "3", "9"],
race: "Elf",
name: "Derolt",
age: "84",
..etc
但是现在,我想要从 API 调用加载初始值。
所以我创建了这个:
const fetchGameCharData = async (gameId) => {
const game = await axios("api/games/" + gameId);
// return the result
return game;
};
我的问题是,我不知道如何使用上面的 fetch 方法来实际填充 Formik 使用的initialValues 部分。
有人这样做过吗?
谢谢!
使用条件渲染方法。
仅在收到 API 调用的响应后才加载表单。显示
loading...
或自定义 spinner
,直到获得 API 响应。
通过这种方法,您的表单可以直接使用
进行加载,而不会出现首次加载时没有值的闪烁情况,并且由于 API 响应,值会在一瞬间出现。initial values
// In your state add two values like
initialValues: [],
isValueLoded: false
...
// Make your API call in `componentDidMount`
componentDidMount() {
// Call your API
fetchGameCharData(....).then(res => {
this.setState({ isValueLoded: true, initialValues: res.values});
}).catch(err => ....);
}
....
// In your render method
render() {
return !this.state.isValueLoded ?
(<div>Loading...</div>) : (
<Formki
values={this.state.initialValues}
....
/>
);
}
如果您使用类组件:
componentDidMount() {
this.fetchGame();
}
async fetchGame() {
const game = await fetchGameCharData(GAME_ID);
this.setState({ game });
}
...
// in render method
const { game } = this.state;
...
<Formik
initialValues={game}
...
如果您使用功能组件:
const { game, setGame } = useState();
useEffect(async () => {
const game = await fetchGameCharData(GAME_ID);
setGame(game);
}, []);
...
// in return
<Formik
initialValues={{
characterClasses: ["1", "3", "9"],
race: "Elf",
name: "Derolt",
age: "84",
...
}}
values={game}
...
只需确保仅在
Formik
可用时渲染 game
即可。
否则会出错,因为 initialValues
要求对象具有表单所需的所有属性。
这是您问题的示例:
const [officeInfo, setOfficeInfo] = useState({})
async function fetchOfficeInfo() {
try {
const response = await iaxios.get(url)
setOfficeInfo(response.data)
} catch (error) {
console.log(error)
}
}
useEffect(() => {
fetchOfficeInfo()
}, [])
....
<Formik
enableReinitialize={true}
initialValues={officeInfo}
...
/>
您还可以将值传递到formik中的
initialValues
对象中。我通常这样做:
假设你的 API 返回一个像这样的对象:
const data = {
characterClasses: ["1", "3", "9"],
race: "Elf",
name: "Derolt",
age: "84",
}
你需要做两件事,
initialValues
对象enableReinitialize
属性设置为 true。 // 这允许 formik
在新值可用时重置表单。interface CharacterType = {
characterClasses: string[],
race: string,
name: string,
age: string,
...others
}
export default function Character() {
const initialValues: CharacterType = {
characterClasses: data?.characterClasses ?? [""], // acts as default value
race: data?.race ?? "",
name: data?.name ?? "",
age: data?.age ?? "",
...others
}
return (
<Formik
initialValues,
enableReinitialize: true,
...others
)
}