【问题标题】:Array of Functional Components doesn't append props content as expected功能组件数组未按预期附加道具内容
【发布时间】:2021-12-28 02:33:33
【问题描述】:

我想将<TokenFeed/> 功能组件的数组添加到<Feeds/> 组件。问题是当我这样做时,将一些文本传递给我的<App/>onClick() 事件无法按预期工作。单击时<TokenFeed/> 的数组版本将替换我的<input/> 文本,而不是附加到它的末尾。

相反,当我在<Feeds/>的返回中添加<TokenFeed/>的副本时, 并单击按钮,它工作正常。

我该如何解决这个问题?

Demo

import React, { useState } from "react";
import { Feeds } from "./Feeds";

export default function App() {
  const [inputValue, setInputValue] = useState("");
  const [showFeeds, setShowFeeds] = useState();

  function createFeeds(e) {
    if (e._reactName === "onClick" && showFeeds === undefined) {
      setShowFeeds(
        <Feeds
          value={(val) => {
            setInputValue(inputValue + val);
            createFeeds("");
          }}
        />
      );
    } else {
      setShowFeeds(undefined);
    }
  }
  return (
    <>
      <input
        type="text"
        placeholder="Message"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)}
      ></input>
      <button onClick={(e) => createFeeds(e)}>Create Feeds</button>
      {showFeeds}
    </>
  );
}
import React from "react";
import { TokenFeed } from "./TokenFeed";

let tokenFeedArr = [];

export const Feeds = (props) => {
  if (tokenFeedArr.length === 0) {
    tokenFeedArr.push(
      <TokenFeed
        key={"1"}
        onClick={() => props.value("Array")}
        tokenName={"Array"}
        tokenPrice={"Test"}
      />
    );
  }

  return (
    <section>
      {/* This doesn't work */}
      {tokenFeedArr}

      {/* This does work */}
      <TokenFeed
        key={"2"}
        onClick={() => props.value("Direct")}
        tokenName={"Direct"}
        tokenPrice={"Test"}
      />
    </section>
  );
};
import React from "react";

export const TokenFeed = (props) => {
  return (
    <section
      onClick={() => props.onClick()}
      style={{ backgroundColor: "yellow", width: "10%", textAlign: "center" }}
    >
      <h1>{props.tokenName}</h1>
      <p>{props.tokenPrice}</p>
    </section>
  );
};

【问题讨论】:

  • 您能分享一下预期的功能吗?理想情况下它应该如何工作?例如,当我在输入中键入“test”并按创建提要时,会发生什么,以及当我键入 append '2' 以使其成为“test2”时,应用程序应该如何表现?
  • 单击创建提要时,您可以选择单击阵列和直接。我希望能够多次单击数组并让它输出“数组”+输入中已经存在的值。 Array 按钮应该与 Direct 按钮完全一样。
  • 我不明白你的问题。如果直接将TokenFeed 渲染为孩子正在工作,那么问题出在哪里?
  • @ALegendsTale 您正在尝试将 JSX 推送到组件外部的数组并呈现它。顺便说一句,将 JSX 存储在 state 中是个坏主意
  • React 101,不要将 JSX 存储在状态或数组等中......存储数据并将其映射到您需要的 JSX。通过这种方式,您将避免一整类 React 陈旧的外壳错误。

标签: javascript reactjs react-hooks react-props react-functional-component


【解决方案1】:

您需要在Feeds 组件中声明let tokenFeedArr = [];

代替:

let tokenFeedArr = [];

export const Feeds = (props) => {
  if (tokenFeedArr.length === 0) {
    tokenFeedArr.push(
      <TokenFeed
        key={"1"}
        onClick={() => props.value("Array")}
        tokenName={"Array"}
        tokenPrice={"Test"}
      />
    );
  }
...

试试这个:

export const Feeds = (props) => {
  const tokenFeedArr = [];
  if (tokenFeedArr.length === 0) {
    tokenFeedArr.push(
      <TokenFeed
        key={"1"}
        onClick={() => props.value("Array")}
        tokenName={"Array"}
        tokenPrice={"Test"}
      />
    );
  }
...

Feeds 组件之外声明的tokenFeedArr 不起作用的原因与JavaScript 闭包有关。具体来说,问题出在value() 函数内,该函数位于tokenFeedArr 内的TokenFeed 实例内。

传递给tokenFeedArrTokenFeed 实例的value() 函数只能访问inputValue,因为它是在组件安装时(这是一个空字符串)。它没有通过 React 状态连接到 inputValue,因为它超出了导出组件的范围。即使TokenFeed 组件被推送到Feeds 组件内的tokenFeedArr,也是如此。 tokenFeedArr 仍然在 Feeds 之外声明。 setInputValue 函数之所以有效,是因为 useState 挂钩的工作原理,但 inputValue 变量只是一个变量,受 JavaScript 闭包/提升的影响,这会使其保留其原始值。

【讨论】:

  • 你完全倒退了。像这样在组件内部声明的是每次渲染都会重置它的版本。至少当它在外部声明时它仍然存在,但因为它不是任何状态的一部分,所以它不会在更新时触发重新渲染。
  • @DrewReese 尝试打开发布的演示 OP 并实施我的解决方案,您会发现它有效。我想也许我的解释有点令人困惑。 tokenFeedArr 实际上并不是管理状态的一种方式。我会尝试更新我的答案以更清楚地解释它。
  • @CarltonLindsay 感谢您的详细解释!它真的帮了我很多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-07
  • 1970-01-01
  • 2020-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多