【问题标题】:How to write a useComponent custom hook in React?如何在 React 中编写 useComponent 自定义钩子?
【发布时间】:2021-12-30 20:52:04
【问题描述】:

我想创建一个自定义钩子useComponent,它返回一个JSX.Element,它将在其他地方呈现。

我试过这个:

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>
  );
}

但它不起作用。一旦我尝试输入输入,什么都没有发生。

我怎样才能做到这一点?

我知道做这样的事情可能是一种不好的做法,但我想要这样做的原因是能够打开一个全局对话框并将c 组件作为children 传递给&lt;Dialog /&gt; 组件所以我既可以在对话框主体内渲染c,也可以访问[value, setValue] 状态。所以我的用例是这样的:

[编辑]

我还用对话框添加了整个逻辑:

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>;
}

【问题讨论】:

    标签: reactjs react-hooks react-context react-component


    【解决方案1】:

    正如你所说,你想返回一个JSX.Element,但实际上每次你的钩子运行时你都会返回一个新组件(一个新函数)。因此,如果您实际上在钩子之外声明您的组件并返回渲染的组件,您就可以实现您的目标。这是一个工作示例:

    import { 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
      };
    };
    
    export default function App() {
      const { element } = useComponent();
    
      return <div className="App">{element}</div>;
    }
    

    【讨论】:

    • 请看看我的编辑。您的解决方案似乎仅在子项在创建状态的组件内呈现时才有效。
    • @entropyfeverone 确实,否则您需要为您的输入创建某种全局状态(可能使用上下文),但我不确定它是否像您想要的那样可扩展。检查这个code sandbox
    • 你能在 Skroutz 推荐我吗? :p
    • 哈哈,我们其实没有推荐系统,但是目前有很多空缺,去吧!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-24
    • 2020-08-09
    • 2020-08-27
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 2020-12-05
    相关资源
    最近更新 更多