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?
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.