skip to Main Content

I am learning React by building a front end to a remote REST API. (I can modify the remote API if needed.) So far, I have a function on the front end like this:

function FooForm() {

const [inputs, setInputs] = useState({});

  const handleChange = (event) => {
    const name = event.target.name;
    const value = event.target.value;
    setInputs(values => ({...values, [name]: value}))
  }

  const handleSubmit = (event) => {
    event.preventDefault();
    // Here is where I'd post to the API
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>Foo
        <input 
          type="text" 
          name="foo" 
          value={inputs.foo || ""} 
          onChange={handleChange}
        />
      </label>
      <br />
      <label>Bar
        <input 
          type="text" 
          name="bar" 
          value={inputs.bar || ""} 
          onChange={handleChange}
        />
      </label>
      <br />
      <input type="submit" />
    </form>
  )
}

It will POST to an API endpoint. But how can I manipulate the form so that the text fields are pre-loaded with values from the database, e.g. something like value={inputs.foo || preload.foo}, and so on?

This poster answered his own question by opting to use the useEffect hook in a certain way, but it is unclear from the context how React/fetch deals with cookies. Does that happen automatically? Is there a better way?

2

Answers


  1. function FooForm() {
      const [inputs, setInputs] = useState({});
    
    + const init = () => {
    +   fetch(/* some setting */).then(res=>setInputs(values => ({...res.data})))
    + }
    
    + useEffect(()=>{
    +   init()
    + },[])
    
      const handleChange = (event) => {
        const name = event.target.name;
        const value = event.target.value;
        setInputs(values => ({...values, [name]: value}))
      }
    
      const handleSubmit = (event) => {
        event.preventDefault();
        // Here is where I'd post to the API
      }
    
      return (
        <form onSubmit={handleSubmit}>
          <label>Foo
            <input 
              type="text" 
              name="foo" 
              value={inputs.foo || ""} 
              onChange={handleChange}
            />
          </label>
          <br />
          <label>Bar
            <input 
              type="text" 
              name="bar" 
              value={inputs.bar || ""} 
              onChange={handleChange}
            />
          </label>
          <br />
          <input type="submit" />
        </form>
      )
    }
    
    Login or Signup to reply.
  2. A few things, the best practice is for your input‘s value to have the initial value of the state inputs which in your case is an object with properties foo and bar instead of using || operator.

    Then to include cookies in your HTTP request it’s nothing related to React but rather the library you are using to make those HTTP request.

    Let’s say you use Fetch API and their way is to include an optional object with a key-value of: credentials: 'include'.

    And no you actually wouldn’t need useEffect hook in this case since you are just POSTing a request, the useEffect is required only if you were to receive the data in the same component, which I don’t see that you are doing that in your current code, but I can add some example since you mentioned that.

    function FooForm() {
    
      const [inputs, setInputs] = useState({
       //initial input values
       foo: "",
       bar: ""
      });
    
      const handleChange = (event) => {
        const name = event.target.name;
        const value = event.target.value;
        setInputs(values => ({...values, [name]: value}))
      }
    
    //Initialize a state for the expected data
      const [dataReceived, setDataReceived] = useState("");
    
      const handleSubmit = (event) => {
        event.preventDefault();
        // Here is where I'd post to the API
    
        // Let's say you are using 'fetch':
        fetch('https://myapi.com', {
         //optional property to include credentials(cookies, etc.)
         method: 'POST',
         credentials: 'include'
         //...the rest of your code here
        }).then(res => res.json()).then(data => {
         setDataReceived(data);
        })
      }
    
      // For useEffect use-case let's say you are expecting to 
      // receive some data after the component renders
      useEffect(() => {
    
       const fetchNewData = () => { 
        fetch('https://myapi.com', {
         method: 'GET',
         credentials: 'include'
        }).then(res => res.json()).then(data => {
         setDataReceived(data);
        })
       };
       fetchNewData();
    
      // Empty dependency array meaning it only runs
      // when the component mounts. If you wish
      // it to re-run when different state changes
      // then add that state in the dependency array
      },[])
    
      return (
       <div>
        <p>My received data: {dataReceived}</p>
        <form onSubmit={handleSubmit}>
          <label>Foo
            <input 
              type="text" 
              name="foo" 
              value={inputs.foo} 
              onChange={handleChange}
            />
          </label>
          <br />
          <label>Bar
            <input 
              type="text" 
              name="bar" 
              value={inputs.bar} 
              onChange={handleChange}
            />
          </label>
          <br />
          <input type="submit" />
        </form>
       </div>
      )
    }
    

    An extra tip: if you were to use a button element inside your form it has, by default, a type="submit" so you don’t have to explicitly code it, but it’s still a best practice to include it.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search