using useState with function calls function when set to another one
Answered
SharpieMaster posted this in #help-forum
"use client";
import React, { useState, type ReactNode, ReactElement, type FC } from "react";
const Modal = ({
children,
}: {
children: [
ReactElement<typeof ModalContainer>,
ReactElement<typeof ModalTrigger>,
];
}) => {
const [hello, setHello] = useState<() => void>(() => {
console.log("old");
});
const [ModalContainer, ModalTrigger] = children;
return (
<>
<ModalContainerBackend setHello={setHello}>
{ModalContainer}
</ModalContainerBackend>
<ModalTriggerBackend hello={hello}>{ModalTrigger}</ModalTriggerBackend>
</>
);
};
export const ModalContainer: FC<{ children: ReactNode }> = ({ children }) => {
return <div key="modal container">{children}</div>;
};
export const ModalTrigger: FC<{ children: ReactNode }> = ({ children }) => {
return <div key="modal trigger">{children}</div>;
};
const ModalContainerBackend: FC<{
setHello: (hello: () => void) => void;
children: ReactNode;
}> = ({ setHello, children }) => {
return (
<div
className="bg-zinc-200 p-4"
onClick={() => setHello(() => console.log("new"))} // When clicked, console log "new" for some reason
>
{children}
</div>
);
};
const ModalTriggerBackend: FC<{
hello: () => void;
children: ReactNode;
}> = ({ hello, children }) => {
return (
<div
onClick={() => console.log(hello)} // Logs undefined, even though it has a default value of () => console.log("old")
className="border p-4"
>
{children}
</div>
);
};
export default Modal;
Answered by SharpieMaster
Solved,
Putting a function in an object fixed the issue, the container was logging "new" because with useState() you can make an expression for your new value useState((prev) => prev + 1), but I was using console.log("new") so it was running it, and set the new value to undefined.
"use client";
import React, { useState, type ReactNode, ReactElement, type FC } from "react";
const Modal = ({
children,
}: {
children: [
ReactElement<typeof ModalContainer>,
ReactElement<typeof ModalTrigger>,
];
}) => {
const [hello, setHello] = useState<{ fn: () => void }>({
fn: () => {
console.log("old");
},
});
const [ModalContainer, ModalTrigger] = children;
return (
<>
<ModalContainerBackend setHello={setHello}>
{ModalContainer}
</ModalContainerBackend>
<ModalTriggerBackend hello={hello}>{ModalTrigger}</ModalTriggerBackend>
</>
);
};
export const ModalContainer: FC<{ children: ReactNode }> = ({ children }) => {
return <div key="modal container">{children}</div>;
};
export const ModalTrigger: FC<{ children: ReactNode }> = ({ children }) => {
return <div key="modal trigger">{children}</div>;
};
const ModalContainerBackend: FC<{
setHello: (value: { fn: () => void }) => void;
children: ReactNode;
}> = ({ setHello, children }) => {
return (
<div
className="bg-zinc-200 p-4"
onClick={() => setHello({ fn: () => console.log("new") })}
>
{children}
</div>
);
};
const ModalTriggerBackend: FC<{
hello: { fn: () => void };
children: ReactNode;
}> = ({ hello, children }) => {
return (
<div onClick={hello.fn} className="border p-4">
{children}
</div>
);
};
export default Modal;
Putting a function in an object fixed the issue, the container was logging "new" because with useState() you can make an expression for your new value useState((prev) => prev + 1), but I was using console.log("new") so it was running it, and set the new value to undefined.
2 Replies
Im trying to create a Modal component and I ran into some strange behavior
This is how I use it on the page,
and whenever I press the ModalContainer it logs "new"
and when I press ModalTrigger it logs undefined even though it has a default value,
I'd really appreciate it if someone could help me with this
Thanks
<Modal>
<ModalContainer>Smoething</ModalContainer>
<ModalTrigger>Trigger</ModalTrigger>
</Modal>
This is how I use it on the page,
and whenever I press the ModalContainer it logs "new"
and when I press ModalTrigger it logs undefined even though it has a default value,
I'd really appreciate it if someone could help me with this
Thanks
Solved,
Putting a function in an object fixed the issue, the container was logging "new" because with useState() you can make an expression for your new value useState((prev) => prev + 1), but I was using console.log("new") so it was running it, and set the new value to undefined.
"use client";
import React, { useState, type ReactNode, ReactElement, type FC } from "react";
const Modal = ({
children,
}: {
children: [
ReactElement<typeof ModalContainer>,
ReactElement<typeof ModalTrigger>,
];
}) => {
const [hello, setHello] = useState<{ fn: () => void }>({
fn: () => {
console.log("old");
},
});
const [ModalContainer, ModalTrigger] = children;
return (
<>
<ModalContainerBackend setHello={setHello}>
{ModalContainer}
</ModalContainerBackend>
<ModalTriggerBackend hello={hello}>{ModalTrigger}</ModalTriggerBackend>
</>
);
};
export const ModalContainer: FC<{ children: ReactNode }> = ({ children }) => {
return <div key="modal container">{children}</div>;
};
export const ModalTrigger: FC<{ children: ReactNode }> = ({ children }) => {
return <div key="modal trigger">{children}</div>;
};
const ModalContainerBackend: FC<{
setHello: (value: { fn: () => void }) => void;
children: ReactNode;
}> = ({ setHello, children }) => {
return (
<div
className="bg-zinc-200 p-4"
onClick={() => setHello({ fn: () => console.log("new") })}
>
{children}
</div>
);
};
const ModalTriggerBackend: FC<{
hello: { fn: () => void };
children: ReactNode;
}> = ({ hello, children }) => {
return (
<div onClick={hello.fn} className="border p-4">
{children}
</div>
);
};
export default Modal;
Putting a function in an object fixed the issue, the container was logging "new" because with useState() you can make an expression for your new value useState((prev) => prev + 1), but I was using console.log("new") so it was running it, and set the new value to undefined.
Answer