I have 2 components, Index.js and Menu.js. Index.js contains Menu.js.
I have a state declared in the top level, Index.js. When you click on the edit icon existing in Index.js, it triggers a toggle on the css display attribute of the state variable. When this is toggled, it does not immediately show the item that now has a changed css value from display: none to display: block. However, if I click inside the area where the Menu.js component is, it then renders and shows the div (mainly because I have some functionality that forces a render with document.onmouseup). UseEffect was placed into Menu.js and is not triggered by the change. It too will only trigger if I click inside the component. Additionally, if no clicking is done inside of the component, it will be one step behind on the toggle.
Menu.js
useEffect(() => {
console.log("do something");
}, [form.display]);
return (
<div style={{ height: "500px", display: form.display }} id="editForm"></div>
);
Index.js
const [form, setForm] = useState({
display: "none",
});
const handleEditForm = () => {
var updateForm;
console.log("triggered");
if (form.display == "none") {
updateForm = form;
updateForm.display = "block";
setForm(updateForm);
} else {
updateForm = form;
updateForm.display = "none";
setForm(updateForm);
}
};
return (
<div>
<img
onClick={handleEditForm}
style={{
position: "relative",
top: "5px",
paddingLeft: "10px",
width: "30px",
}}
src="/public/static/images/edit_icon.svg"
alt="edit icon"
/>
</div>
);
Note: There is a conditional onMouseDown, onMouseMove and OnMouseUp function
This is a basic concept of Javascript and React. React compares objects before deciding a state variables has changed. Since objects are compared with referential equality, your changing it (or mutating it, in JS terms) does not trigger a rerender.
As you can notice, your objects still point to the same address:
//according to your code
let form = { display : 'none' };
let updateForm;
updateForm = form;
updateForm.display = "block";
console.log(updateForm === form);
You need to create a new address. Notice how below two objects are not equal even when having same properties.
//How to create a different object
const updateForm = { display : "none" };
updateForm.display = "block";
const updateForm2 = { ...updateForm, display : "block"};
console.log(updateForm === updateForm2);
You have to do something similar. I have used spread operator but you can create your object again (since only one property). No need to create that extra variable
setForm({display : "none"});
setForm({display : "block"});