Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/402.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 添加道具类型以渲染道具功能_Javascript_Reactjs_Typescript_Visual Studio Code_React Proptypes - Fatal编程技术网

Javascript 添加道具类型以渲染道具功能

Javascript 添加道具类型以渲染道具功能,javascript,reactjs,typescript,visual-studio-code,react-proptypes,Javascript,Reactjs,Typescript,Visual Studio Code,React Proptypes,使用常规react组件时,有多种方法可以为组件启用intellisense(通过功能组件的属性类型或jsdoc注释),但如果组件使用如下呈现属性模式: 返回this.props.children({config,onClickConfig}) 使用方法如下: { ({config,onClickConfig})=>({config}) } 是否有任何方法可以为config对象或onClickConfig函数的类型启用intellisense 我看到typescript可以通过重用使用者中的

使用常规react组件时,有多种方法可以为组件启用intellisense(通过功能组件的属性类型或jsdoc注释),但如果组件使用如下呈现属性模式:

返回this.props.children({config,onClickConfig})
使用方法如下:


{
({config,onClickConfig})=>({config})
}
是否有任何方法可以为
config
对象或
onClickConfig
函数的类型启用intellisense


我看到typescript可以通过重用使用者中的类型来实现这一点,但是使用jsdocs或prop类型是否可以实现这一点呢?

我想应该同时使用和document

const propTypes = {
  children: PropTypes.func.isRequired,
  // ... other proptypes
}

/**
 * @param {object} props the props object
 * @param {({ config: React.ElementType, onClickConfig: function }) => React.ElementType} props.children the render prop
 */
const ConsumerComponent = ({ children, ...props }) => ( ..... );
ConsumerComponent.propTypes = propTypes;
问题 不幸的是,
PropTypes
不允许在运行时对函数的(render prop)参数进行类型检查。如果您使用的是Typescript,那么无效的参数类型应该会阻止在构建时编译(如果设置为true)。但是,由于您试图在运行时键入,因此必须使用自己的自定义验证器函数

解决方案

单击
打开模式
按钮将抛出错误。要更正错误,请将其更改为
布尔值

虽然此示例非常随意,因为渲染道具没有公开,但如果要将
isOpen
状态提升到
App
组件,则仍需要检查
Modal
组件中的
isOpen
道具类型是否为布尔值(使用
PropTypes
或自定义验证器)

代码 App.js

import * as React from "react";
import Modal from "./Modal";
import "uikit/dist/css/uikit.min.css";
import "./styles.css";

const App = (): React.ReactElement => (
  <div className="app">
    <Modal>
      {({ isOpen, toggleModal }): React.ReactElement => (
        <>
          <h1 className="title">Hello!</h1>
          <p className="subtitle">
            The modal is currently {isOpen ? "visible" : "hidden"}!
          </p>
          <p className="subtitle">There are two ways to close this modal:</p>
          <ul>
            <li>Click outside of this modal in the grey overlay area.</li>
            <li>Click the close button below.</li>
          </ul>
          <button
            className="uk-button uk-button-danger uk-button-small"
            onClick={toggleModal}
          >
            Close
          </button>
        </>
      )}
    </Modal>
  </div>
);

export default App;
index.tsx

import * as React from "react";
import * as ReactDOM from "react-dom";
import PropTypes from "prop-types";
import withTypeCheck from "./withTypeCheck";

export type ChildrenProps = {
  isOpen: boolean;
  toggleModal: () => void;
};

export type ChildFunc = ({
  isOpen,
  toggleModal
}: ChildrenProps) => React.ReactElement;

export type ModalProps = {
  children: ChildFunc;
};

/**
 * Reuseable Modal component
 *
 * @param children - a render prop that accepts an object of `isOpen` and `toggleModal` props
 * @returns a ReactElement
 * @example <Modal>({ isOpen, toggleModal }) => (...)}</Modal>
 */
const Modal = ({ children }: ModalProps): React.ReactElement => {
  const [isOpen, setVisible] = React.useState(false);
  const wrapperRef = React.useRef<HTMLDivElement>(null);

  const toggleModal = React.useCallback(() => {
    setVisible((prevState) => !prevState);
  }, []);

  const closeModal = React.useCallback(
    (e: Event): void => {
      if (
        isOpen &&
        wrapperRef.current &&
        !wrapperRef.current.contains(e.target as Node)
      ) {
        toggleModal();
      }
    },
    [isOpen, toggleModal]
  );

  React.useEffect(() => {
    document.addEventListener("click", closeModal, { capture: true });

    return () => {
      document.removeEventListener("click", closeModal, { capture: true });
    };
  }, [closeModal]);

  return (
    <>
      <button
        className="uk-button uk-button-primary uk-button-small"
        type="button"
        onClick={toggleModal}
      >
        Open Modal
      </button>
      {isOpen &&
        ReactDOM.createPortal(
          <>
            <div className="overlay" />
            <div className="window-container">
              <div className="modal-container">
                <div ref={wrapperRef} className="modal">
                  {withTypeCheck(children, { isOpen: "true", toggleModal })}
                </div>
              </div>
            </div>
          </>,
          document.body
        )}
    </>
  );
};

Modal.propTypes = {
  children: PropTypes.func.isRequired
};

export default Modal;
import * as React from "react";
import * as ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);
import*as React from“React”;
从“react dom”导入*作为react dom;
从“/App”导入应用程序;
ReactDOM.render(
,
document.getElementById(“根”)
);

这很有帮助。我从中获得了灵感,并向消费者展示了函数的参数
import * as React from "react";
import * as ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById("root")
);