Reputation: 1
Hello guys I'm having hard time on changing a single object property from another from child side.
import ComboData from './ComboData.js'
export default function BasicTabs() {
const [country, setCountry] = useState({ selectedID: 0, data: [{ id: 1, text: "USA" }, { id: 2, text: "PORTUGAL" }] });
return(
<div>
<ComboData type="text" name={"country"} label={"Country"} selectd={country.selectedID}
valueData={country.data} idRef={"data.id"} valRef={"data.text"}
setValOut={setCountry({...country, [country.selectedId]})}
placeholder={"Select Your Country"}
/>
</div>
(
ON THE OTHER SIDE...
function ComboData({ name, label, placeholder, value, idRef, valRef, setValOut}) {
return (
<div>
<label htmlFor={name}>{label}</label>
<select onChange={(e) => setValOut(e.target.value)} name={name} value={selectd}>
<option value="0" disabled>{placeholder}</option>
{valueData ? (valueData.length > 0 ?
valueData.map(
(item, index) => <option key={item[idRef]} value={item[idRef]} id={item[idRef]}>{item[valRef]}</option>
) : (
<option disabled>empty</option>
)
) : (
<option disabled>empty</option>
)}
</select>
</div>
)
}
export default ComboData;
I expeted that when a option is selected from my ComboData it has to update only the SelectedID of the useState.. LIKE THIS...
FROM:
country{[{ selectedID: 0, data: [{ id: 1, text: "USA" }, { id: 21, text: "PORTUGAL" }]}
TO:
country{[{ selectedID: 1, data: [{ id: 1, text: "USA" }, { id: 2, text: "PORTUGAL" }]}
OR
country{[{ selectedID: 2, data: [{ id: 1, text: "USA" }, { id: 21, text: "PORTUGAL" }]}
ISSUES:
1- Uncaught TypeError: Cannot read properties of undefined (reading 'data')
2- By DELETING the Line valueData={country.data}
===> Uncaught Error: Too many re-renders. React limits the number of renders to prevent an infinite loop.
at renderWithHooks (react-dom.development.js:16187:1)
Upvotes: 0
Views: 269
Reputation: 92
There are some issues with your code. First, you need to pass the props with the exact same name to your component. For example, you defined:
function ComboData({ /*...*/ value, /*...*/ })
But passed:
<ComboData
/*...*/
valueData={country.data}
/*...*/
/>
Second, but related to the first, you used valueData
inside ComboData
, but the prop name is value
as shown above.
Third, passing big object props like these can cause a lot of problems, because:
country.selectedId
changes, all options
from map updates, because the state have changed.Additionally, I think that first error occurs due to useState
"set..." not being instantaneous. You can't use await in it, but it does need some time to change the state. I'd recommend a loading state to make sure it had enough time to update.
However, I'd recommend you to refactor it to something like this instead:
const [selectedCountryId, setSelectedCountryId] = useState(0)
const [countryOptions, setCountryOptions] = useState([{...}, {...}])
And pass those as separated props
An optimization could be done if countryOptions
(equivalent to your country.data
) never changes:
const countryOptions = [{...}, {...}]
Hope this helps. Good luck!
Upvotes: 0