提问者:小点点

为什么当我把我的道具传递给一个功能组件时,它在最初存在后就不再存在了?


这是我传递onClick属性的函数(setshowmodel是来自useState钩子的setState()):

<MyFunctionalComponent
  onClick={() => setShowModal(true)}
  ...other props here
/>

这是接收道具的功能组件:

export const MyFunctionalComponent = ({ onClick }) => {
  return (
   <section>
     ...other code here
     {onClick && (<Button>{ctaText}</Button>)}
   </section>
  );
};

但是按钮组件从未出现,因为prop onClick未定义。当我安慰的时候。将道具记录在功能组件中,它最初会在控制台中打印该功能,但随后会打印两次未定义的道具。有人能解释一下为什么会这样吗?我是通过传播。。。取而代之的是道具。但是控制台。日志保持不变?我不明白为什么。这是我关于堆栈溢出的第一个问题,请随时给我反馈如何提出更好的问题:)


共3个答案

匿名用户

您收到“未定义”响应的原因是@Zrogua提到,onClick是一个事件侦听器函数,而不是一个持久值(如您定义的状态)。

import React from "react";

const YourButton = ({ onClick }) => {
  console.log(onClick);

  return <section>{onClick && <button>here</button>}</section>;
};

const ParentDiv = () => {
  return (
    <div>
      <h1>Button Props</h1>
      <h2>Start editing to see some magic happen!</h2>
      <YourButton onClick={() => console.log("CLICK")} />
    </div>
  );
};

export default ParentDiv;

控制台的结果。log()

函数on点击()//index.js:27: 25

这是因为道具是只读的。从React文档:

无论您将组件声明为函数还是类,它都不能修改自己的道具...这样的函数被称为“纯”,因为它们不试图改变它们的输入,并且总是为相同的输入返回相同的结果。

因此,只有定义了onclick函数,按钮才会显示。例如,如果你没有给onClark一个函数或值,按钮将不会出现:

import React, { useState } from "react";

const YourButton = ({ onClick }) => {
  console.log(onClick);
  return (
    <section>
      {onClick && <button>This button is shown if a button is defined.</button>}
    </section>
  );
};

const ParentDiv = () => {
  return (
    <div>
      <h1>Button Props</h1>
      <YourButton onClick={() => console.log("CLICK")} />
      <YourButton /> {/* You won't see this button because the function is not defined. */}
    </div>
  );
};

export default ParentDiv;

该按钮之所以出现,是因为该道具具有一个未定义的值(您的onClick函数),并且由于它是只读的,您无法在子组件中访问该函数。

相反,(1)在父组件中定义模态状态,(2)通过道具将状态传递给按钮,如下所示:


import React, { useState } from "react";

const YourButton = ({ onClick }) => {
  console.log(onClick);
  return (
    <section>
      {onClick && <button>This button is shown if a button is defined.</button>}
    </section>
  );
};

const AltButton = ({ modal }) => {
  return (
    <section>
      {modal && (
        <button>This button is shown the modal state is passed.</button>
      )}
    </section>
  );
};

const ParentDiv = () => {
  const [modal, setModal] = useState(false);
  return (
    <div>
      <h1>Button Props</h1>
      <YourButton onClick={() => console.log("CLICK")} />
      <YourButton />{" "}
      {/* You won't see this button because the function is not defined. */}
      <section>
        <button onClick={() => setModal(!modal)}>OPEN MODAL</button>
      </section>
      {modal && <p>this is dependent on state</p>}
      <AltButton modal={modal} />
    </div>
  );
};

export default ParentDiv;

工作代码沙盒:https://codesandbox.io/s/stack-66715327-passingfunctions-92pzr

最后,如果我在字里行间阅读,并且正确地理解了当模态打开时,您希望隐藏一个按钮,那么下面是一个用于打开模态的按钮的模态包装技巧:https://codesandbox.io/s/stack-66715327-modalwrapper-wvl54

匿名用户

不能传递onClick,onClick只是一个事件侦听器。你应该通过这个州

<MyFunctionalComponent onClick={() => setShowModal(!showModal)}
      showModal={showModal}
      ...other props here />
/>


export const MyFunctionalComponent = ({ showModal }) => {
    return (
        <section>
            ...other code here
            {showModal && (<Button>{ctaText}</Button>)}
        </section>
   );
};

我相信这应该行得通。让我知道这是否是你要找的。

匿名用户

我认为,比起传递回调,您应该传递决定组件是否应该显示的变量。检查这个例子。

export const MyFunctionalComponent = ({ isShow, onClick }) => {
  return (
    <section>
      ...other code here
      {isShow && <div>something</div>}
    </section>
  );
};

export default function App() {
  const [showModal, setShowModal] = useState(false);
  return (
    <MyFunctionalComponent
      isShow={showModal}
      onClick={() => setShowModal(true)}
    />
  );
}

我还认为你可能会犯错误,并有其他想法。。这样地:

<section>
  ...other code here
  <button onClick={ onClick }>something</button>}
</section>