通过 API 调用设置表单的初始值

问题描述 投票:0回答:4

在我的 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 部分。

有人这样做过吗?

谢谢!

reactjs react-hooks formik
4个回答
7
投票

使用条件渲染方法。

仅在收到 API 调用的响应后才加载表单。显示

loading...
或自定义
spinner
,直到获得 API 响应。

通过这种方法,您的表单可以直接使用

initial values
进行加载,而不会出现首次加载时没有值的闪烁情况,并且由于 API 响应,值会在一瞬间出现。

编辑

// 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}
         ....
         />
    );
}

3
投票

如果您使用类组件:

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
要求对象具有表单所需的所有属性。


1
投票

这是您问题的示例:

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}
  ...
  />


0
投票

您还可以将值传递到formik中的

initialValues
对象中。我通常这样做:

假设你的 API 返回一个像这样的对象:

const data = {
  characterClasses: ["1", "3", "9"],
  race: "Elf",
  name: "Derolt",
  age: "84",
}

你需要做两件事,

  1. 将值传递到 formik
    initialValues
    对象
  2. 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
  )
}
© www.soinside.com 2019 - 2024. All rights reserved.