javascript - 如何使用 Context api 传递组件?
问题描述
如果标题有点不清楚,我很抱歉,但我正在制作一个类似于 Notion 的应用程序,所以我想打开一个菜单并选择我想要添加的组件。待办事项列表、图像、表格等。如何将菜单中的组件传递回 Board 组件?我正在使用 onclick 处理程序设置菜单中的项目,并将其添加到我在上下文中设置的数组中。我将该数组带入板组件并通过它进行映射。我认为这会起作用,但没有任何东西呈现在板上。我做了一个控制台日志并看到正在添加的东西,但浏览器将它们视为对象?这是我的代码:
const NewComponentMenu = () => {
const { setComponent } = useContext(NewComponentContext);
return (
<div className="w-6 h-6 mt-4 ml-4 bg-white shadow-md text-gray-800 font-Inter">
<Menu>
<Menu.Button>
<div className="p-1 rounded-lg bg-blue-500 hover:bg-blue-600 ease-in-out duration-100">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6 text-blue-50"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M10 3a1 1 0 011 1v5h5a1 1 0 110 2h-5v5a1 1 0 11-2 0v-5H4a1 1 0 110-2h5V4a1 1 0 011-1z"
clipRule="evenodd"
/>
</svg>
</div>
</Menu.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items as="div" className="w-60 shadow-lg rounded-lg">
<h1 className="text-center font-Inter text-2xl pb-2">Items</h1>
<Menu.Item>
{({ active }) => (
<button
id="Todo"
onClick={() => setComponent(<Todo />) }
className={`${
active ? "bg-blue-500 text-white" : "text-black"
} flex items-center py-2 px-3 rounded-lg w-full`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-6 w-6 mr-3"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-3 7h3m-3 4h3m-6-4h.01M9 16h.01"
/>
</svg>
Todo list
</button>
)}
</Menu.Item>
</Menu.Items>
</Transition>
</Menu>
</div>
);
};
export default NewComponentMenu;
董事会组件
const Board = () => {
const { components } = useContext(NewComponentContext);
console.log(components)
return (
<div className="flex items-center z-50">
<NewComponentMenu />
{components.map((component, i) => {
<div className="h-40 w-40 bg-gray-500 z-50" key={i}> {component}</div>
})}
</div>
);
};
export default Board;
上下文
const NewComponentState: NewComponentsState = {
components: [],
setComponent: () => {}
}
export const NewComponentContext = React.createContext<NewComponentsState>(NewComponentState);
export const NewComponentProvider: React.FC = ({ children }) => {
const [components, setComponents] = useState(NewComponentState.components)
const setComponent = (newComponent: any) => setComponents((components) => [...components, newComponent])
return (
<NewComponentContext.Provider value={{components, setComponent}}>
{children}
</NewComponentContext.Provider>
);
}
...
解决方案
好的,所以在板组件中,我将 map 函数移出 return 并做了
let renderedArray = components.map((component, i) => {
return <div className="" key={i}> {component}</div>
})
为什么这行得通,为什么我以前的方式行不通?