Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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

I want to add an array of <TokenFeed/> functional components to the <Feeds/> component. The problem is that when I do, the onClick() event that passes some text to my <App/> doesn’t work as expected. The array version of <TokenFeed/> when clicked, will replace my <input/> text rather than appending to the end of it.

On the contrary, when I add a copy of <TokenFeed/> in the return of <Feeds/>,
and click the button, it works fine.

How can I fix this?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

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>
  );
};

>Solution :

You need to declare let tokenFeedArr = []; inside the Feeds component.

Instead of:

let tokenFeedArr = [];

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

Try this:

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

The tokenFeedArr variable defined outside of the scope of the Feeds function is not handled in the same way as React state. The value gets re-initialized on re-rendering of the component. The tokenFeedArr declared in Feeds.js pertains to the instance of the Feeds component, and so should be declared inside the component itself.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading