Search code examples
reactjsreact-state-managementrecoiljs

Post data through API with RecoilJS


In RecoilJS docs, there is an example how to handle asynchronous data queries, but it's only about get data.

Let say I have a simple state:

const accountState = atom({
  key: "accountState",
  default: {
    id: "",
    name: "",
  }
});

And a component which is a register form:

const RegisterForm = () => {
  return (
    <form>
      <input type="text" name="username" />
      <button type="submit">Register</button>
    </form>
  )
}

The posted data is in FormData. After successfully created new account, the server will send a response that contains id and name of the account.

{
  "id": "abcdef123456",
  "name": "example"
}

This response data will be set as a new state of accountState.

How can I handle the process in RecoilJS?


Solution

  • You can just handle with http request and set the response to the state.

    const RegisterForm = () => {
      const [account, setAccount] = useRecoilState(accountState);
    
      const handleSubmit = async e => {
        e.preventDefault();
    
        const response = await fetch(url, {
          method: 'POST',
          body: data,
        });
    
        const responseJson = await response.json();
        setAccount(responseJson);
      };
    
      return (
        <form onSubmit={handleSubmit}>
          <input type="text" name="username" />
          <button type="submit">Register</button>
        </form>
      );
    }
    

    Edit

    To have a reusable approach, I will suggest to build custom hooks for frequent usage

    const useRegister = () => {
      const setAccount = useSetRecoilState(accountState);
    
      const register = useCallback(async (username)=> {
        const response = await fetch(url, {
          method: 'POST',
          body: { username },
        });
    
        const responseJson = await response.json();
        setAccount(responseJson);
      }, [setAccount]);
    
      return register;
    
    }
    
    const RegisterForm = () => {
      const register = useRegister();
    
      const handleSubmit = async e => {
        e.preventDefault();
    
        await register(username);
      };
    
      return (
        <form onSubmit={handleSubmit}>
          <input type="text" name="username" />
          <button type="submit">Register</button>
        </form>
      );
    }