Getting empty data from state when using useState React hook

拈花ヽ惹草 提交于 2020-11-29 21:30:30

问题


I've stumbled upon an issue with the useState scope. I'm trying to create a dynamic Bootstrap Form where the user will be able to add more rows to the group (those rows will containt energy-related data). So, when I add 2+ rows and start changing inputs' values, enterEnvironmentData function fires empty data (last console.log). Where is my mistake? Why state data ( groupsData.group0.rows array ) is empty?

const { useState, useEffect } = React;

const App = () => {

const [ defaultData, ] = useState(
    {
        envName: undefined,
        heatingCosts: 0,
        waterCosts: 0,
        gasCosts: 0,
        environmentCosts: 0,
        frazzle: 0
    }
);
const [ groupsData, setGroupsData ] = useState( {
    group0: {
        id: 0,
        rowsAmount: 0,
        rows: []
    }
} );

// *enterEnvironmentData* function fires when input fields are changed

const enterEnvironmentData = (event) => {
    console.log(event.target.value);
    const group = event.target.getAttribute('data-group'),
        row = event.target.getAttribute('data-row');
    
    console.log("groupsData - ", groupsData);
    console.log("data-group - ", group);
    console.log("data-row - ", row);
    console.log("groupsData[", group, "]", groupsData[group]);
    console.log("groupsData[", group, "].rows", groupsData[group].rows); // rows array is empty ???
};

let [ environment, setEnvironment] = useState( {
    group0: [],
    group1: []
} );

// *toggleChangeRowsAmount* fires when changing Form.Control's value (elements amount)

const toggleChangeRowsAmount = (event) => {
    console.log(event.target);
    let value = +event.target.value,
        name = event.target.name;

    if ( value <= 0 ) {
        value = 0;
    } else {
        setGroupsData({
            ...groupsData,
            [name]: { ...groupsData[name], rowsAmount: value }
        })
    }
};

// *addRows* fires when clicking on "Add" button

const addRows = (event) => {
    const name = event.target.getAttribute('name'),
        rows = groupsData[name].rowsAmount,
        length = groupsData[name].rows.length;
    let arr = [],
        rowNames = [];
    
    for (let i = length; i < rows+length; i++) {
        let newRow = `row${i}`;
        rowNames.push(newRow);
        arr.push(
            {
                [newRow]: defaultData
            }
        );
    }

    setGroupsData({
        ...groupsData,
        [name]: {
            ...groupsData[name],
            rows: [
                ...groupsData[name].rows,
                ...arr
            ]
        }
    });

    let items = [];
    
    for (let i = 0; i < arr.length; i++ ) {
        let rn = rowNames[i];
        items.push(
            <div key={ rowNames[i] }>
                <div>
                    <label>
                        Environment
                    </label>
                    <input
                        type="text"
                        data-group={ name }
                        data-row={ rn }
                        value={ arr[i][rn].envName }
                        onChange={ enterEnvironmentData }
                    />
                </div>
                <div>
                    <label>
                        Heating Costs
                    </label>
                    <input
                        type="number"
                        data-group={ name }
                        data-row={ rn }
                        value={ arr[i][rn].heatingCosts }
                        onChange={ enterEnvironmentData }
                    />
                </div>
                <div>
                    <label>
                        Water Costs
                    </label>
                    <input
                        type="number"
                        data-group={ name }
                        data-row={ rn }
                        value={ arr[i][rn].waterCosts }
                        onChange={ enterEnvironmentData }
                    />
                </div>
                <div>
                    <label>
                        Gas Costs
                    </label>
                    <input
                        type="number"
                        data-group={ name }
                        data-row={ rn }
                        value={ arr[i][rn].gasCosts }
                        onChange={ enterEnvironmentData }
                    />
                </div>
                <div>
                    <label>
                        Environment Costs
                    </label>
                    <input
                        type="number"
                        data-group={ name }
                        data-row={ rn }
                        value={ arr[i][rn].environmentCosts }
                        onChange={ enterEnvironmentData }
                    />
                </div>
                <div>
                    <label>
                        Frazzle
                    </label>
                    <input
                        type="number"
                        data-group={ name }
                        data-row={ rn }
                        value={ arr[i][rn].frazzle }
                        onChange={ enterEnvironmentData }
                    />
                </div>
            </div>
        );
    };

    setEnvironment({
        ...environment,
        [name]: [
            ...environment[name],
            ...items
        ]
    });
};

useEffect(
    () => {
        console.log("groupsData - ", groupsData, ", environment - ", environment);
    },
    [ groupsData, environment ]
)
    
return (
    <div className="EntryForm">
        <div className="container">
            <form>
                <div key="group0" >
                    <h4>
                        Group
                    </h4>
                    <label>
                        Elements Amount                      
                        <input
                            type="number"
                            name="group0"
                            value={ groupsData["group0"].rowsAmount }
                            onChange={ toggleChangeRowsAmount }
                        />
                        <button
                            name="group0"
                            onClick={ addRows }
                        >
                            Add
                        </button>
                    <label>
                    {
                        environment["group0"].map( env => env)
                    }
                </div>
            </Form>
        </div>            
    </div>
)
};
ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>  
<div class="react"></div>

P.S. Nothing is submited at this form yet.

I noticed that necessary data isn't empty when I add rows at least twice

来源:https://stackoverflow.com/questions/64804386/getting-empty-data-from-state-when-using-usestate-react-hook

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!