ReactJS update a component stored in state array

Viewed 76

I'm pretty new to coding so I hope my question won't sound too ridiculous. I've spent days to figure something out but didn't find anything. So I have a react page with the main component that is my "planning container". In this component, I have a child component that represents a whole month. it's a table with a line for each people and my team, and a td that represents each day of the month. This child is stored in a variable array that is stored in the state. When I click on a button, I create another child (for the next month), that I will push into the array stored in the state.

I have a variable called "refresh" that just setRefresh(!refresh). This variable is passed to the childs components and I put this variable in the useEffect [] that will trigger a re-render. => The problem is that it doesn't re-render at all.

So, just for you to know, I really need to be able to "append" a whole month at each click on the button. I really need this "view" to be able to work. I will paste some code to make you understand the main idea.

here is the parent :

    import React, {useEffect, useState} from "react";
    import PlanningMonthBuild from "./PlanningMonthBuild";
    import './Planning.css';
    import "react-datepicker/dist/react-datepicker.css";
    
    const PlanningBuild = () => {
        const [startForNextMonth, setStartForNextMonth] = useState(new Date());
        const [inputList, setInputList] = useState([]);
        const [refresh, setRefresh] = useState(false);
    
        useEffect(() => {
            initPlanning();
        }, []);
    
        const handleRefresh = () => {
            setRefresh(!refresh);
        }
    
        const initPlanning = () => {
            let date = new Date(startForNextMonth.getFullYear(), startForNextMonth.getMonth(), 1);
            let newPlanning = [...inputList];
            newPlanning.splice(0, 0,
                <PlanningMonthBuild
                    key={'current' + new Date().toISOString()}
                    startDate={date}
                    refresh={refresh}
                />
            );
            let date2 = new Date(startForNextMonth.getFullYear(), startForNextMonth.getMonth() + 1, 1);
            date2.setMonth(date.getMonth() + 1);
            setStartForNextMonth(date2);
            setInputList(newPlanning);
        };
    
        const addOneMonthNext = () => {
            setInputList(inputList.concat(
                 <PlanningMonthBuild
                      key={new Date().toISOString()}
                      startDate={startForNextMonth}
                      refresh={refresh}
                 />
            ));
            let date = startForNextMonth;
            date.setDate(1);
            date.setMonth(date.getMonth() + 1);
            setStartForNextMonth(date);
        };
    
        return (
            <main>
                <div className="refresh-div" onClick={handleRefresh}><i className="fa fa-refresh" aria-hidden="true"></i></div>
                <button className="myButton" onClick={addOneMonthNext}>Add Next Month</button>
                <div id="insideDiv">
                    {inputList}
                </div>
            </main>
        );
    };
    
    export default PlanningBuild;

And here is the child (that build each month) :

    import React, {useEffect, useState} from "react";
    import useAxiosPrivate from "../hooks/useAxiosPrivate";
    import {getFirstDayOfMonth} from "../utils/dates";
    
    const PlanningMonthBuild = ({ startDate, refresh }) => {
        const [dateDebut] = useState(startDate);
        const [jsListe, setJsListe] = useState([]);
        const axiosPrivate = useAxiosPrivate();
    
        useEffect(() => {
            let isMounted = true;
            const controller = new AbortController();
    
            try {
                axiosPrivate.get('api/planning/team?start=' + getFirstDayOfMonth(dateDebut.getFullYear(), dateDebut.getMonth()), {
                    signal: controller.signal
                }).then(response => {
                    if (isMounted) {
                        const newListeJS = response.data;
                        setJsListe(newListeJS);
                    }
    
                });
    
            } catch (err) {}

            return () => {
                isMounted = false;
                controller.abort();
            }
    
        }, [refresh])
    
        return (jsListe.map((day)=> {
            ///.... building a table(tr,td...)
        }))
    
    }
    
    export default PlanningMonthBuild;

So, when I put my child component directly into the parent return, it works when I click on refresh button (if my workmate updates something for example...), it will update my table but if I store my child component in the array in "inputList" state it doesn't...

I hope you can understand what I mean.

Thanks in advance for any help.

0 Answers
Related