问题
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