Here's a codesandbox to show you how to reset the items: https://codesandbox.io/s/romantic-heisenberg-93qi7
I also left a note for you on how to get this to work with your API data, see the comment inside onChangeText()
The problem is that the inputs are not controlled by state as you have deduced. We should create an updated object for each item from your API, giving it a value prop.
index.js
import React from "react";
import ReactDOM from "react-dom";
import Cart from "./Cart";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
Items: [],
itemvalues: [{}]
};
this.onChangeText = this.onChangeText.bind(this);
this.getItems = this.getItems.bind(this);
this.handleReset = this.handleReset.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.findFieldIndex = this.findFieldIndex.bind(this);
this.trimText = this.trimText.bind(this);
}
getItems = () => {
/*if the data is coming from an API, store it in an array then .map() over it.
we can add a value prop to the object like:
so you can do something like:
const newItems = [...apiData].map((item) => {
return {
...item,
value: ""
}
})
this.setState({
Items: newItems
})
*/
this.setState({
Items: [
{
name: "item1",
description: "item1",
group: "groupA",
dtype: "str",
value: ""
},
{
name: "item2",
description: "item2",
group: "groupA",
dtype: "str",
value: ""
},
{
name: "item3",
description: "item3",
group: "groupB",
dtype: "str",
value: ""
},
{
name: "item4",
description: "item4",
group: "groupB",
dtype: "str",
value: ""
}
]
});
};
onChangeText = e => {
const updatedItems = [...this.state.Items].map(item => {
if (item.name === e.target.name) {
return {
...item,
value: e.target.value
};
} else {
return item;
}
});
const updatedItemValues = [...updatedItems].reduce((obj, curr) => {
if (!obj[curr.group]) {
obj[curr.group] = [];
}
obj[curr.group] = [...obj[curr.group], { [curr.name]: curr.value }];
return obj;
}, {});
this.setState({
...this.state,
Items: updatedItems,
itemvalues: updatedItemValues
});
};
findFieldIndex = (array, name) => {
return array.findIndex(item => item[name] !== undefined);
};
trimText(str) {
return str.trim();
}
handleReset = () => {
const resetedItems = [...this.state.Items].map(item => {
return {
...item,
value: ""
};
});
this.setState(
{
...this.state,
Items: resetedItems,
itemvalues: []
},
() => console.log(this.state)
);
};
handleSubmit = () => {
console.log(this.state.itemvalues);
};
render() {
return (
<div>
{
<Cart
Items={this.state.Items}
getItems={this.getItems}
handleSubmit={this.handleSubmit}
handleReset={this.handleReset}
onChangeText={this.onChangeText}
/>
}
</div>
);
}
}
Cart.js
import React, { useEffect } from "react";
import Form from "./Form";
const Cart = props => {
useEffect(() => {
props.getItems(props.Items);
}, []);
return (
<div>
<Form Items={props.Items} onChangeText={props.onChangeText} />
<button onClick={props.handleSubmit}>Submit</button>
<button onClick={props.handleReset}>Reset</button>
</div>
);
};
export default Cart;
The Cart component can remain mostly the same, we do not need to pass in props.items to useEffect() dependency.
Form.js
import React from "react";
const Form = props => {
return (
<div>
{props.Items.map(item => {
return (
<input
name={item.name}
placeholder={item.description}
data-type={item.dtype}
data-group={item.group}
onChange={e => props.onChangeText(e)}
value={item.value}
/>
);
})}
</div>
);
};
export default Form;
Now in Form component, we provide each input a value prop that is connected to the item our upper-most parent component-state.
That's pretty much all you need to reset the values.