Search code examples
reactjsformsreact-router-domdefault-valuereact-dom

react-router-dom i can't printing the default value from the form to another page


I want to print the information I get from the form on the info page when I press the send button. However, when the information is taken as default value, it does not come to the info page.

Information from the form needs to be printed on the Info page

My App.js

import React, { useState } from 'react'
import './App.css';
import { Route, Routes } from 'react-router-dom'
import Info from './Info';
import Form from './Form';

function App() {

  const [form, setForm] = useState({ name: "", city: "", birth: "", color: "", address: "" });

  const handleChange = (event) => {
    setForm({ ...form, [event.target.name]: event.target.value })
  }

  return (
    <div className="App">
      <h2>Enter your informations</h2>
      <Routes>
        <Route path="/" exact element={<Form form={form} onChange={handleChange}/>}></Route>
        <Route path="/info" element={<Info form={form}/>}></Route>
      </Routes>
    </div>
  );
}

export default App;

My Form.js

import React from 'react'
import { Link } from 'react-router-dom'

function Form({ form, HandleChange }) {
    return (
        <div>
            <form>
                <input type="text" name="isim" defaultValue={form.name} onChange={HandleChange} placeholder="Enter your name" />
                <select name="city" defaultValue={form.city} onChange={HandleChange}>
                    <option defaultValue="">Enter your city</option>
                    <option defaultValue="Ankara">Ankara</option>
                    <option defaultValue="İstanbul">İstanbul</option>
                    <option defaultValue="İzmir">İzmir</option>
                </select>
                <input type="date" name="birth" defaultValue={form.birth} onChange={HandleChange}  />
                <input type="color" name="color" defaultValue={form.color} onChange={HandleChange} />
                <textarea name="address" placeholder="Enter your address" cols="20" rows="5" defaultValue={form.adsress} onChange={HandleChange}></textarea>
                <Link to="/info"><button>Send</button></Link>
            </form>
        </div>
    )
}

export default Form

My Info.js

import React from 'react'
import { Link} from 'react-router-dom'

function Info({form}) {
  return (
    <div>
      <p>Name: {form.name} </p>
      <p>City: {form.city}</p>
      <p>Birthday: {form.birth}</p>
      <p>Color: {form.color}</p>
      <p>Address: {form.address}</p>
      <Link to="/"><button>Back</button></Link>
    </div>
  )
}

export default Info

Solution

  • First issue is that the Form component is passed an onChange prop but is destructuring a HandleChange prop.

    <Route
      path="/"
      element={<Form form={form} HandleChange={handleChange} />}
    />
    

    Fix this to pass a consistently named prop.

    <Route
      path="/"
      element={<Form form={form} onChange={handleChange} />}
    />
    

    The second issue from what I can see of the code it seems the button element is submitting the form and since the default form action is not prevented the page/app is reloading. HTML button elements have type="submit" by default if not specified.

    Make sure that the name attribute for the "name" field matches the React state key. In other words, ensure it is name="name" instead of name="isim".

    Additionally, all these form fields should technically be controlled inputs since you are attaching an onChange handler to each. Controlled inputs use the value prop instead of the defaultValue prop.

    You've a couple options:

    1. Declare the button to not be a form submit button.

      function Form({ form, onChange }) {
        return (
          <div>
            <form>
              <input
                type="text"
                name="name"
                value={form.name}
                onChange={onChange}
                placeholder="Enter your name"
              />
              <select name="city" value={form.city} onChange={onChange}>
                <option disabled value="">Enter your city</option>
                <option value="Ankara">Ankara</option>
                <option value="İstanbul">İstanbul</option>
                <option value="İzmir">İzmir</option>
              </select>
              <input
                type="date"
                name="birth"
                value={form.birth}
                onChange={onChange}
              />
              <input
                type="color"
                name="color"
                value={form.color}
                onChange={onChange}
              />
              <textarea
                name="address"
                placeholder="Enter your address"
                cols="20"
                rows="5"
                value={form.adsress}
                onChange={onChange}
              ></textarea>
              <Link to="/info">
                <button type="button">Send</button>
              </Link>
            </form>
          </div>
        );
      }
      
    2. Declare a form submit handler and prevent the default form action and issue the imperative navigation action.

      import { useNavigate } from 'react-router-dom';
      
      function Form({ form, onChange }) {
        const navigate = useNavigate();
      
        const submitHandler = (e) => {
          e.preventDefault();
          navigate("/info");
        };
      
        return (
          <div>
            <form onSubmit={submitHandler}>
              <input
                type="text"
                name="name"
                value={form.name}
                onChange={onChange}
                placeholder="Enter your name"
              />
              <select name="city" value={form.city} onChange={onChange}>
                <option disabled value="">Enter your city</option>
                <option value="Ankara">Ankara</option>
                <option value="İstanbul">İstanbul</option>
                <option value="İzmir">İzmir</option>
              </select>
              <input
                type="date"
                name="birth"
                value={form.birth}
                onChange={onChange}
              />
              <input
                type="color"
                name="color"
                value={form.color}
                onChange={onChange}
              />
              <textarea
                name="address"
                placeholder="Enter your address"
                cols="20"
                rows="5"
                value={form.adsress}
                onChange={onChange}
              ></textarea>
              <button type="submit">Send</button>
            </form>
          </div>
        );
      }
      

    In either case you'll still want to be explicit about the button type for readability and maintainability reasons.

    Demo

    Edit react-router-dom-i-cant-printing-the-default-value-from-the-form-to-another-pag