Search code examples
reactjscomponents

Refresh a Component from sibling Component in React


I have 2 sibling components namely <AddTask/> and <TaskList/> which are children of <Home/> component. Currently, when I add a new task in my ToDo App, it will be added but I need to refresh the page in order for it to display the new task. How can I refresh the <TaskList/> component immediately after I click the Add button in <AddTask/> component?

Here is my <AddTask/> Component


const AddTask = () => {
    const [task, setTask] = useState("");
    const [isPending, setIsPending] = useState(false);

    const handleClick = (e)=> {
        e.preventDefault();
        setIsPending(true);
        const todo = {task};

        fetch('http://localhost:8000/tasks', {
            method: 'POST',
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(todo)
        })
        .then(()=>{
            setIsPending(false);
        })

    };

    return ( 
    
        <form className="new-task" onSubmit={handleClick}>
            <input className="input" 
                type="text" 
                required
                value={task}
                onChange= { (e)=> setTask(e.target.value) } 
            />
            <button className="add-task">Add</button>
        </form>
        
    );
}
 
export default AddTask;

This is the <Home/> Component

import TaskList from "./TaskList";
import useFetch from "./useFetch";

const Home = () => {
    const { data: task, isPending, error} = useFetch('http://localhost:8000/tasks');

    return (
        <div className="home">
            <AddTask />
            { error && <div>Failed to fetch data.</div> }
            { isPending && <div>Loading...</div> }
            { task && <TaskList task={task} /> }
        </div>
    );
}
 
export default Home;

Solution

  • In Home component, you need a tasks state so you can update that state in AddTask component

    Home

    import TaskList from "./TaskList";
    import useFetch from "./useFetch";
    import { useState, useEffect } from 'react'
    
    const Home = () => {
        const [tasks, setTasks] = useState(null);
        const { data: task, isPending, error} = useFetch('http://localhost:8000/tasks');
        useEffect(() => {
            if (task) setTasks(task)
        }, [task])
    
        return (
            <div className="home">
                <AddTask setTasks={setTasks} />
                { error && <div>Failed to fetch data.</div> }
                { isPending && <div>Loading...</div> }
                { tasks && <TaskList task={tasks} /> }
            </div>
        );
    }
     
    export default Home;
    

    AddTask

    const AddTask = ({ setTasks }) => {
        const [task, setTask] = useState("");
        const [isPending, setIsPending] = useState(false);
    
        const handleClick = (e)=> {
            e.preventDefault();
            setIsPending(true);
            const todo = {task};
    
            fetch('http://localhost:8000/tasks', {
                method: 'POST',
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify(todo)
            })
            .then(()=>{
                setIsPending(false);
                setTasks(prev => ([...prev, task]))
            })
    
        };
    
        return ( 
        
            <form className="new-task" onSubmit={handleClick}>
                <input className="input" 
                    type="text" 
                    required
                    value={task}
                    onChange= { (e)=> setTask(e.target.value) } 
                />
                <button className="add-task">Add</button>
            </form>
            
        );
    }
     
    export default AddTask;