功能组件数组未按预期附加道具内容

Array of Functional Components doesn't append props content as expected

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

相反,当我在<Feeds/>的return中添加<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>
  );
};

您需要在 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 的实例中

传递给 tokenFeedArr 内部的 TokenFeed 实例的 value() 函数只能访问 inputValue ,就像安装组件时一样(这是一个空字符串)。它没有通过 React 状态连接到 inputValue,因为它在导出组件的范围之外。即使 TokenFeed 组件被推送到 Feeds 组件内的 tokenFeedArr 也是如此。 tokenFeedArr 仍然在 Feeds 之外声明。 setInputValue 函数可以工作,因为 useState 钩子是如何工作的,但是 inputValue 变量只是一个变量并且受制于 JavaScript closures/hoisting,这导致它保留其原始值。