【问题标题】:why does my prop cease to exist after initially existing when I pass it through to a functional component?当我将它传递给功能组件时,为什么我的道具在最初存在后不再存在?
【发布时间】:2021-06-17 06:49:36
【问题描述】:

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

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

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

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

但是 Button 组件永远不会出现,因为属性 onClick 是未定义的。当我 console.log 功能组件内的道具时,它最初在控制台中打印该功能,但随后又打印了两次未定义。有人可以解释为什么会这样吗?我通过传播 ...props 来实现它。但是console.log 保持不变?我不明白为什么。这是我在 Stack Overflow 上的第一个问题,请随时给我反馈,告诉我如何提出更好的问题 :)

【问题讨论】:

  • 这听起来不对。首先 - 为什么你的组件会连续渲染 3 次?

标签: javascript reactjs react-props


【解决方案1】:

您收到“未定义”响应的原因是因为正如 @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;

console.log() 的结果:

function onClick() // index.js:27:25

之所以这样是因为props是read-only。来自 React 文档:

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


因此,您的按钮只有在定义了onClick 函数时才会显示。比如你没有给onClick一个函数或者值,按钮就不会出现:

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;

出现按钮是因为 prop 的值不是未定义的(您的 onClick 函数),并且因为它是只读的,所以您无法在子组件中访问该函数。


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


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

【讨论】:

    【解决方案2】:

    我认为与其传递回调,不如传递决定组件是否显示的变量。检查这个例子。

    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>
    

    【讨论】:

      【解决方案3】:

      你不能传递 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>
         );
      };
      

      我相信这应该可行。让我知道这是否是您想要的。

      【讨论】:

        猜你喜欢
        • 2020-08-07
        • 2016-10-19
        • 2016-09-03
        • 2017-02-19
        • 2020-08-20
        • 1970-01-01
        • 2022-01-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多