Setting initial values of a form via an API call

Viewed 5924

In my React game, I use a React library called Formik for a form.

In it, you set the initial values for the form like this:

<Formik
    initialValues={{
        characterClasses: ["1", "3", "9"],
        race: "Elf",
        name: "Derolt",
        age: "84",
        
        ..etc
        

But now, I'm in a situtation where I want to load the initial values from an API call.

So I created this:

const fetchGameCharData = async (gameId) => {
    const game = await axios("api/games/" + gameId);
    // return the result
    return game;
};

My problem is, I can't figure out how to use the above fetch method to actually populate the initialValues part that Formik uses.

Has anyone ever done this?

Thanks!

2 Answers

Use conditional-rendering approach.

Load your form only after you get the response from API call. Show loading... or a custom spinner until you get API response.

With this approach, your form directly load with initial values without any flickering of having no values at first load and values comes up in a flash as a result of API response.

Edit

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

If you are using class component:

componentDidMount() {
    this.fetchGame();
}

async fetchGame() {
    const game = await fetchGameCharData(GAME_ID);
    this.setState({ game });
}
...
// in render method
const { game } = this.state;
...
<Formik
    initialValues={game}
...

If you are using functional component:

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

Just make sure to render the Formik only when the game is available. Otherwise it will be error as initialValues require an object has all properties needed for the form.

Related