How to collect form fields value using Ref and Forwarded Ref

In App.js using the “Add Project” button manage or create new project form with handleStartAddProject function, handle the form fields value using handleAddProject function.

function handleStartAddProject(){
    SetProjectState(prevState => {
      return {
        ...prevState,
        selectedProjectID: null
      };
    })
  }

  function handleAddProject(projectData){
    SetProjectState(preState => {
      const newProject = {
        ...projectData,
        id: Math.random()
      };
      return {
        ...preState,
        projects: [...preState.projects, newProject]
      };
    })
  }

Receive fields value with onclick event using handleSave function in newproject component.

    function handleSave(){
        const enteredTitle = title.current.value;alert(enteredTitle)
        const enteredDescription = description.current.value;
        const enteredDueDate = dueDate.current.value;

        onAdd({
            title: enteredTitle,
            description: enteredDescription,
            dueDate: enteredDueDate
        });
    }

Use forwardRef in input component for ref and props

const Input = forwardRef(function Input({ label, textarea, ...props}, ref ){
    const classes = "w-full p-1 border-b-2 rounded-sm border-stone-300 bg-stone-200 text-stone-600 focus:outline-none focus:border-stone-600"

return ( <p className="flex flex-col gap-1 my-4">
        <label className="text-sm font-bold uppercase text-stone-500">{label}</label>
        {textarea ? (
            <textarea ref={ref} {...props} className={classes}  />
            ) : ( <input ref={ref} {...props} className={classes} />
            )}
        </p>
)
})

Create button component for getting button value using props

export default function Button({children, ...props}){
    return  <button className="px-4 py-2 text-xs md:text-base rounded-md bg-stone-700 text-stone-400 hover:bg-stone-600 hover:text-stone-100 " {...props}> {children}</button>
}

Output:

Complete code:

App.js

import React, { useState } from "react";
import ProjectSidebar from './Components/ProjectSidebar'
import NewProject from './Components/NewProject'
import NoProjectSelected from './Components/NoProjectSelected'

export default function App() {

  const [projectState, SetProjectState] = useState({
    selectedProjectID: undefined,
    projects: []
  });

  function handleStartAddProject(){
    SetProjectState(prevState => {
      return {
        ...prevState,
        selectedProjectID: null
      };
    })
  }

  function handleAddProject(projectData){
    SetProjectState(preState => {
      const newProject = {
        ...projectData,
        id: Math.random()
      };
      return {
        ...preState,
        projects: [...preState.projects, newProject]
      };
    })
  }
  console.log(projectState)


  let content;
  if(projectState.selectedProjectID === null){
    content = <NewProject onAdd={handleAddProject}/> 
  } else if(projectState.selectedProjectID === undefined){
    content = <NoProjectSelected onStartAddProject={handleStartAddProject}/>
  }
  return (
    <main className='h-screen my-8 flex gap-8'>
      <ProjectSidebar onStartAddProject={handleStartAddProject}/>
      {content}
    </main>
   
  )
}

ProjectSidebar.js

import Button from './Button'

export default function ProjectSidebar({onStartAddProject}){
    return (
        <aside className="w-1/3 px-8 py-16 bg-stone-900 text-stone-50 md:w-72 rounded-r-xl">
            <h2 className="mb-8 font-bold uppercase md:text-xl text-stone-200">My Projects</h2>
            <div>
            <Button onClick={onStartAddProject}> + Add Project</Button>
            </div>
            <ul></ul>
        </aside>
    )

}

NewProject.js

import { useRef } from 'react'
import Input from './Input'
export default function NewProject({onAdd}){
    const title = useRef();
    const description = useRef();
    const dueDate = useRef();

    function handleSave(){
        const enteredTitle = title.current.value;
        const enteredDescription = description.current.value;
        const enteredDueDate = dueDate.current.value;

        onAdd({
            title: enteredTitle,
            description: enteredDescription,
            dueDate: enteredDueDate
        });
    }

    return <div className='w-[35-rem] mt-16'>
        <menu className='flex items-center justify-end gap-4 my-4'>
            <li><button className='bg-stone-800 text-stone-50 hover:bg-stone-950 px-6 py-2 rounded-md' onClick={handleSave}>Save</button></li>
            <li><button className='text-stone-800 hover:text-stone-950'>Cancel</button></li>
        </menu>
        <div>
            <Input ref={title} label="title"/>
            <Input ref={description} label="description" textarea/>
            <Input ref={dueDate} label="dueDate"/>
           
        </div>
    </div>

}

Input.js

import { forwardRef } from "react"

const Input = forwardRef(function Input({ label, textarea, ...props}, ref ){
    const classes = "w-full p-1 border-b-2 rounded-sm border-stone-300 bg-stone-200 text-stone-600 focus:outline-none focus:border-stone-600"

return ( <p className="flex flex-col gap-1 my-4">
        <label className="text-sm font-bold uppercase text-stone-500">{label}</label>
        {textarea ? (
            <textarea ref={ref} {...props} className={classes}  />
            ) : ( <input ref={ref} {...props} className={classes} />
            )}
        </p>
)
})

export default Input;

NoProjectSelected.js

import Button from './Button'

export default function NoProjectSelected ({onStartAddProject}){
    return(
        <div className="mt-24 text-center w-2/3">
            <h2 className="text-xl font-bold text-stone-500 my-4">No Project Selected</h2>
            <Button onClick={onStartAddProject}>Create new project</Button>

        </div>
    )
}

Button.js

export default function Button({children, ...props}){
    return  <button className="px-4 py-2 text-xs md:text-base rounded-md bg-stone-700 text-stone-400 hover:bg-stone-600 hover:text-stone-100 " {...props}> {children}</button>
}

Run your application using ” npm start ” command

Keep Learning 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *