I want to create a custom hook useComponent which returns a JSX.Element that will be rendered elsewhere.
I have tried this:
import { useState} from 'react';
const useComponent = () => {
const [value, setValue] = useState('');
const c = () => {
return <>
<p>Component</p>
<input value={value} onChane={(e) => setValue(e.target.value)} />
</>
}
return {
c,
value,
}
}
export default function App() {
const {c: C} = useComponent();
return (
<div className="App">
<C />
</div>
);
}
but it does not work. Once I try typing on input, nothing happens.
How can I achieve this ?
I know it might be a bad practice to do such a thing, but the reason I want this is to be able to open a global dialog and pass the c component as children to the <Dialog /> component so I can both render c inside the dialog's body and also have access to the [value, setValue] state. So my use case would be something like:
[EDIT]
I also add the whole logic with dialog:
import { createContext, useContext, useState } from "react";
const Test = ({ value, setValue }) => {
return (
<>
<p>Component</p>
<input value={value} onChange={(e) => setValue(e.target.value)} />
</>
);
};
const useComponent = () => {
const [value, setValue] = useState("");
return {
element: <Test value={value} setValue={setValue} />,
value
};
};
const DialogCTX = createContext({});
export function DialogProvider(props) {
const [component, setComponent] = useState(null);
const ctx = {
component,
setComponent
};
return (
<DialogCTX.Provider value={ ctx }>
{props.children}
</DialogCTX.Provider>
);
}
export const useDialog = () => {
const {
component,
setComponent,
} = useContext(DialogCTX);
return {
component,
setComponent,
}
};
const Dialog = () => {
const { component } = useDialog();
return <div>
<p>Dialog</p>
{component}
</div>
}
const Setter = () => {
const {element, value} = useComponent();
const {setComponent} = useDialog();
return <div>
<p>Setter component</p>
<p>{value}</p>
<button onClick={() => setComponent(element)}>Set</button>
</div>
}
export default function App() {
return <div className="App">
<DialogProvider>
<Setter />
<Dialog />
</DialogProvider>
</div>;
}