Reputation: 181
I declared a parent component called EditLinksModal
that uses the useState
hook. It has a state property hasError
, which is a JS object whose fields are passed to multiple URLField child components.
However, the child does not seem to be getting the updated props. In fact, it seems that re-rendering isn't happening even though I am calling setHasError
since any console.log
statements in the child don't print anything.
I have 3 console.log
statements below. The 2 console.log
statements in the parent (EditLinksModal
) are printing the correct and up-to-date state properties. However, the console.log
in the child does not even execute. What am I doing wrong ?
Is this because I am using useState
in combination with a local state property that is a JS Object (ie. hasError
is an object, but not a really deeply-nested one). Even so, I am puzzled why the hasError
state property is properly updated, but the child-component doesn't have its error
prop updated.
const URLField = ({label, name, placeholder, value, onHandleChange, error, errorText}) => {
console.log(error) // problem: not even executing or printing anything
return (
<>
<Header5>{label}</Header5>
<CustomInput
name={name}
placeholder={placeholder}
variant="text"
value={value}
onChange={(evt) => onHandleChange(name, evt.target.value)}
/>
{error && <SystemComponent color={theme.colors.alertAction}>{errorText}</SystemComponent>}
</>
)
}
const EditLinksModal = ({visible, handleCloseModal}) => {
const [hasError, setHasError] = useState({
facebookUrl: false,
linkedInUrl: false,
githubUrl: false,
websiteUrl: false
});
const validateUrl = (errorList, fieldName, fieldValue, allowedHostsList = false) => {
// .........
}
const handleSave = (evt) => {
evt.preventDefault();
const errors = hasError;
validateUrl(errors, 'facebookUrl', formValues['facebookUrl'], ['facebook.com']);
validateUrl(errors, 'githubUrl', formValues['githubUrl'], ['github.com']);
validateUrl(errors, 'linkedInUrl', formValues['linkedInUrl'], ['linkedin.com']);
validateUrl(errors, 'websiteUrl', formValues['websiteUrl']);
console.log(errors); // this prints correct, up-to-date values
setHasError(errors);
}
console.log(hasError); // this prints correct, up-to-date values
return (
<SystemComponent>
<URLField
label="Facebook"
name="facebookUrl"
placeholder="Search"
value={formValues["facebookUrl"]}
error={hasError.facebookUrl}
errorText={"Please Enter Valid Facebook Profile Url."}
onHandleChange={handleChange}
/>
</SystemComponent>
)
Upvotes: 1
Views: 521
Reputation: 37327
Your problem is that the state object errors
has the same reference, thus setHasError
does not update the state. If you want to mutate that same object errors
, then use spread operator to create a new object with the same properties:
const handleSave = (evt) => {
evt.preventDefault();
const errors = hasError;
validateUrl(errors, 'facebookUrl', formValues['facebookUrl'], ['facebook.com']);
validateUrl(errors, 'githubUrl', formValues['githubUrl'], ['github.com']);
validateUrl(errors, 'linkedInUrl', formValues['linkedInUrl'], ['linkedin.com']);
validateUrl(errors, 'websiteUrl', formValues['websiteUrl']);
console.log(errors); // this prints correct, up-to-date values
// Use spread operator to create a new object
setHasError({ ...errors });
}
Upvotes: 1