renakre
renakre

Reputation: 8291

Lifting up the state to the main component in React application using hooks

I am learning reactjs and trying to implement small things for practice. The idea is simple, to add records (feedbackTasks) to the database and list these records (when first time page is loaded and later when a new record is added). Please see the image below.

enter image description here

The main component is ManageFeedbackTasks. I keep the list of the feedbackTask items in its state (st_feedbackTaskList). The update of this list is performed through add_to_st_feedbackTask function. If the first time this list is generated, all the fetched data (coming from PrintFeedbackTasks component) is set to the st_feedbackTaskList. If not, only the added item (coming from ShowAddingFeedbackTaskForm) is inserted in the list.

export function ManageFeedbackTasks() {
    const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);

    const add_to_st_feedbackTask = (data) => {

        if (st_feedbackTaskList.length == 0) {
            setFeedbackTaskList(data);
        } else {
            const { id, title, description } = data;
            setFeedbackTaskList([...st_feedbackTaskList, { id, title, description }]);
        }
    }

    return (
        <>
            <ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
            <PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
        </>
    );
}

Below is the PrintFeedbackTasks function. This function receives the feedbackTasks list from the main component ManageFeedbackTasks. This list is first time fetched from the database using fetchFeedbackTasks. Inside fetchFeedbackTasks, props.onListingFeedbackTasks(response.data) sends the fetched list back to the main component to update the state (st_feedbackTaskList).

const PrintFeedbackTasks = (props) => {    
    const [st_isInitialized, setInitialized] = useState(false);    

    const fetchFeedbackTasks = () => {
        axios.get('api/FeedbackTask/Index')
            .then(response => props.onListingFeedbackTasks(response.data))
            .catch(error => console.log(error));
    }    

    useEffect(() => {
        if (!st_isInitialized) {
            fetchFeedbackTasks();
        }
        setInitialized(true);
    });

    return (
        <React.Fragment>
           {
                props.feedbackTasks.map(taskItem =>....
           }
        </React.Fragment>
    );
}

The component below displays the Add form and handles the form submission. When a new item is added, this new item is again sent back to the main component using props.onAddingItem.

const ShowAddingFeedbackTaskForm = (props) => {
    const [st_title, setTitle] = useState('');
    const [st_description, setDescription] = useState('');

    const handleSubmit = async (event) => {
        event.preventDefault();
        await axios(...)
        .then(function (response) {
                setTitle('');
                setDescription('');

            //This will update the list of the feedback task in the main component
                props.onAddingItem({
                   id: response.data,
                   title: st_title,
                   description: st_description
                });

            //GET THE ID HERE
            console.log(response.data);

        }).catch(function (error) {
            console.log(error);
        });
    }


    return (
        <form onSubmit={handleSubmit}>
            <input
                placeholder="Title..."
                type="text"
                value={st_title}
                onChange={(event) => setTitle(event.target.value)}
            />
            <input
                placeholder="Description..."
                type="text"
                value={st_description}
                onChange={(event) => setDescription(event.target.value)}
            />
            <button>Add Feedback Task</button>
        </form>
    );
}

I wonder if this way of lifting and managing the state is robust. Any suggestions to improve the code? Also, I wonder if I should put these components into their own pages (for example, one page or adding a record and another one for listing). Would this make more sense in the react world?

Upvotes: 1

Views: 884

Answers (1)

Shubham Khatri
Shubham Khatri

Reputation: 281666

The idea to lift the state up to the parent is correct. However due to your code structure you could be causing a lot of re-renders and a few performance optimizations can be made in your solution. One more thing is that instead of fetching feedbackTasks in PrintFeedbackTasks component you should do it in the parent itself. Also useEffect takes a second parameter which you can use to execute it on initial mount

You can use useCallback hook to memoize functions too.

ManageFeedbackTasks

export function ManageFeedbackTasks() {
    const [st_feedbackTaskList, setFeedbackTaskList] = useState([]);

    const fetchFeedbackTasks = useCallback(() => {
        axios.get('api/FeedbackTask/Index')
            .then(response => props.onListingFeedbackTasks(response.data))
            .catch(error => console.log(error));
    }, []);    

    useEffect(() => {
        fetchFeedbackTasks();
    }, []);

    const add_to_st_feedbackTask = useCallback((data) => {

        setFeedbackTaskList(prevTaskList => {
          if (prevTaskList.length == 0) {
            return data;
          } else {
            const { id, title, description } = data;
            return [...prevTaskList, { id, title, description }];
          }
        });
    }, [])

    return (
        <>
            <ShowAddingFeedbackTaskForm onAddingItem={add_to_st_feedbackTask} />
            <PrintFeedbackTasks onListingFeedbackTasks={add_to_st_feedbackTask} feedbackTasks={st_feedbackTaskList} />
        </>
    );
}

PrintFeedbackTasks

const PrintFeedbackTasks = (props) => {    

    return (
        <React.Fragment>
           {
                props.feedbackTasks.map(taskItem =>....
           }
        </React.Fragment>
    );
}

As far as the idea to split show and update TaskList is concerned it as product decision which can be made depending on how long is the list of fields that the user needs to fill at once

Upvotes: 1

Related Questions