React中函数组件数组触发onClick未按预期追加input内容如何修复
问题原因
- 第一个问题是
tokenFeedArr定义在<Feeds>组件外部,属于全局变量,仅会在<Feeds>第一次渲染时初始化一次。数组中存储的<TokenFeed/>绑定的onClick回调,捕获的是第一次渲染时的闭包值:当时<App>传入的value回调里的inputValue永远是初始空字符串,所以每次点击都会将输入框内容设置为空 + "Array",看起来就是替换了原有内容。 - 直接写在
<Feeds>返回值里的<TokenFeed/>每次组件重渲染都会生成新的onClick回调,能拿到最新的props.value,所以功能正常。 - 额外的隐患:你在
<App>里直接将组件实例存在showFeeds状态中,也会导致组件捕获的闭包值不会更新,同时setInputValue直接使用当前作用域的inputValue也存在闭包捕获旧值的问题。
修复方案
1. 修改<App>中状态更新逻辑为函数式更新
函数式更新可以直接拿到最新的状态值,不依赖当前闭包捕获的旧值,同时调整状态逻辑,不要将组件实例存在状态中:
import React, { useState } from "react"; import { Feeds } from "./Feeds"; export default function App() { const [inputValue, setInputValue] = useState(""); const [showFeeds, setShowFeeds] = useState(false); function createFeeds(e) { if (e?._reactName === "onClick" && !showFeeds) { setShowFeeds(true); } else { setShowFeeds(false); } } return ( <> <input type="text" placeholder="Message" value={inputValue} onChange={(e) => setInputValue(e.target.value)} ></input> <button onClick={(e) => createFeeds(e)}>Create Feeds</button> {showFeeds && <Feeds value={(val) => { // 函数式更新直接获取最新的输入框值 setInputValue(prev => prev + val); createFeeds(""); }} />} </> ); }
2. 修改<Feeds>组件,移除全局的tokenFeedArr
将数组放到组件内部,每次渲染都能绑定最新的props.value:
import React from "react"; import { TokenFeed } from "./TokenFeed"; export const Feeds = (props) => { // 数组移到组件内部,每次渲染生成最新的组件实例 const tokenFeedArr = [ <TokenFeed key={"1"} onClick={() => props.value("Array")} tokenName={"Array"} tokenPrice={"Test"} /> ]; return ( <section> {tokenFeedArr} <TokenFeed key={"2"} onClick={() => props.value("Direct")} tokenName={"Direct"} tokenPrice={"Test"} /> </section> ); };
<TokenFeed>组件无需修改,保持原有逻辑即可。修改后两个<TokenFeed/>点击后都会将内容追加到输入框末尾,符合预期。
内容的提问来源于stack exchange,提问作者ALegendsTale
相关产品推荐
相关产品推荐

