首页 > 解决方案 > 如何使用 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>
    );
}

...

标签: javascriptreactjs

解决方案


好的,所以在板组件中,我将 map 函数移出 return 并做了

let renderedArray = components.map((component, i) => {
    return <div className="" key={i}> {component}</div>
  })

为什么这行得通,为什么我以前的方式行不通?


推荐阅读