I am new to React, and I am having the following issue:
When I get a value from redux
, I am creating a clone of it and saving it to useState
so I can modify it without affecting the original value until I press save, which then sends the value to redux to be updated in my store. The problem I am having, is in the function saveProject
the value doesn’t change name
within the object, as it is still the original value. However, in the effect
, the correct value is displayed. I am not sure why, what would be causing this?
Here is an example (Open the console to see output).
Note: I have tried changing defaultValue
to value
, but then I cannot type into the input box which leads me to believe maybe there is something else going on?
const [isEditDialogOpen, setIsEditDialogOpen] = useState(true);
return (
{isEditDialogOpen && <EditProjectDialog onClose={() => setIsEditDialogOpen(false)} />}
)
// Simplified: <Dialog />
export default ({ children }) => {
const DialogOutput = <div>{children}</div>
return <>{createPortal(DialogOutput,document.body)}</>
}
// Edit dialog: <EditProjectDialog />
export default () => {
// Original value from redux
const active = useSelector(selectActiveProject);
// The value I want to track
const [project, setProject] = useState<Project>(Object.assign({}, active));
// The value should be the updated value here (but shows the original)
const saveProject = () => console.log(project);
// Sets the value when the input is typed into
const nameChange = (e: BaseSyntheticEvent) => setProject({ ...project, name: e.target.value });
// Prints the correct value from the input
useEffect(() => console.log('useEffect', project), [project]);
return (
<Dialog>
<input defaultValue={project.name} onChange={nameChange} />
<button onClick={saveProject}>Save</button>
</Dialog>
);
}
2
Answers
I am not so sure that this isn’t working as much as that the saveProject function has the initial version of project. To check if this is the problem I would make a useCallback function:
Other than that typically you want to use the value field instead of the defaultValue because the defaultValue field makes this an uncontrolled component and it doesn’t seem like that’s what you want in this case ๐
The problem is with the
defaultValue
props.defaultValue vs value:
I believe that it will work if you change to