I'm quite new to React and can't seem to figure out how to resolve this issue. Maybe a stupid question but here it goes.
I'm trying to make a system where each Person can add skills and a rating of those skills. Each array consist of a skill element as a string and a star element as an integer. I've made some dynamic inputfields with an add and a remove function for more/less inputfields.
For each inputfield I have an onchange function handleChangeInput and this works fine with skills as this is has a property of "name".
Now when trying to fetch the value from ReactStars I get the error: Uncaught TypeError: Cannot read properties of undefined (reading 'name'). This error is called from the handleChangeInput function. ReactStars doesn't have any property of type either.
How will I be able to fetch the value from ReactStars, if it's even possible? I want to set the useState of inputfields with the values of skill and stars of course.
The component I use is: react-rating-stars-component
https://www.npmjs.com/package/react-rating-stars-component
Hope this explains the problem. Otherwise let me know. Thanks.
const [data, setData] = useState({});
const [inputField, setInputField] = useState([{ skill: "", stars: 0 }]);
const handleChangeInput = (index, event) => {
const values = [...inputField];
values[index][event.target.name] = event.target.value;
setInputField(values);
setData(values);
};
const handleAddFields = () => {
setInputField([...inputField, { skill: "", stars: 0 }]);
};
const handleRemoveFields = (index) => {
const values = [...inputField];
console.log(inputField.length);
values.splice(index, 1);
setInputField(values);
setData(values);
};
return(
<div>
{inputField?.map((inputField, index) => (
<div key={index}>
<Row>
<Col xs={5} md={5}>
<Form.Group as={Col}>
<Form.Control
className="mb-3"
type="text"
id="skill"
name="skill"
value={inputField?.skill}
onChange={(event) => handleChangeInput(index, event)}
/>
</Form.Group>
</Col>
<Col xs={4} md={4}>
<Form.Group>
<ReactStars
type="number"
name="stars"
count={5}
size={24}
id="stars"
onChange={(event) => handleChangeInput(index, event)}
color="rgba(230, 230, 230, 255)"
emptyIcon={<i className="fa-solid fa-star"></i>}
filledIcon={<i className="fa-solid fa-star"></i>}
value={inputField.stars}
/>
</Form.Group>
</Col>
<Col xs={3} md={3}>
<div className="btn-section">
<button
type="button"
className="round-btn"
onClick={() => handleAddFields()}
>
<i className="fa-solid fa-plus"></i>
</button>
<button
type="button"
className="round-btn"
onClick={() => handleRemoveFields(index)}
>
<i className="fa-solid fa-minus"></i>
</button>
</div>
</Col>
</Row>
</div>
))}
</div>
);
The package passes the new value, not an event containing it.
You can instead simply bind the change handler differently in each case such that the context you need is passed through:
const [data, setData] = useState({});
const [inputField, setInputField] = useState([{ skill: "", stars: 0 }]);
const handleChangeInput = (index, name, value) => {
const values = [...inputField];
values[index][name] = value;
setInputField(values);
setData(values);
};
const handleAddFields = () => {
setInputField([...inputField, { skill: "", stars: 0 }]);
};
const handleRemoveFields = (index) => {
const values = [...inputField];
console.log(inputField.length);
values.splice(index, 1);
setInputField(values);
setData(values);
};
return(
<div>
{inputField?.map((inputField, index) => (
<div key={index}>
<Row>
<Col xs={5} md={5}>
<Form.Group as={Col}>
<Form.Control
className="mb-3"
type="text"
id="skill"
name="skill"
value={inputField?.skill}
onChange={(event) => handleChangeInput(index, 'skill', event.target.value)}
/>
</Form.Group>
</Col>
<Col xs={4} md={4}>
<Form.Group>
<ReactStars
type="number"
name="stars"
count={5}
size={24}
id="stars"
onChange={(newValue) => handleChangeInput(index, 'stars', newValue)}
color="rgba(230, 230, 230, 255)"
emptyIcon={<i className="fa-solid fa-star"></i>}
filledIcon={<i className="fa-solid fa-star"></i>}
value={inputField.stars}
/>
</Form.Group>
</Col>
<Col xs={3} md={3}>
<div className="btn-section">
<button
type="button"
className="round-btn"
onClick={() => handleAddFields()}
>
<i className="fa-solid fa-plus"></i>
</button>
<button
type="button"
className="round-btn"
onClick={() => handleRemoveFields(index)}
>
<i className="fa-solid fa-minus"></i>
</button>
</div>
</Col>
</Row>
</div>
))}
</div>
);