React父组件内多子组件点击触发onChange回调函数错乱问题如何解决
问题成因
- HTML规范要求页面元素的
id必须全局唯一,你的两个ChildComponent实例内部的input都使用了相同的id="single",对应的label的htmlFor属性也都绑定了single值。 - 点击label时,浏览器会默认触发页面中第一个匹配对应id的input元素的交互事件,因此首次点击第二个子组件的图标时,实际触发的是第一个子组件内绑定了
function1的input的onChange事件,才会出现逻辑错位的问题。你先点击第一个按钮后功能恢复正常属于浏览器交互状态更新带来的偶发表现,核心根因还是id重复。
解决方案
以下三种方案任选一种即可:
方案1:input嵌套在label内部(最简方案,无需id)
利用label的原生特性,将input放在label内部时,点击label内的任意元素都会自动触发关联input的交互,无需设置id和htmlFor:
const ChildComponent = (props) => { return( <> <div className='button'> <label> <FontAwesomeIcon icon={faImage} color='#3B5998' size='5x' /> <input type='file' onChange={props.onChange} style={{ display: 'none' }} /> </label> </div> </> ) }
方案2:使用React内置useId生成唯一id(React 18+推荐)
每个子组件实例独立生成唯一id,避免全局冲突:
import { useId } from 'react' const ChildComponent = (props) => { const inputUniqueId = useId() return( <> <div className='button'> <label htmlFor={inputUniqueId}> <FontAwesomeIcon icon={faImage} color='#3B5998' size='5x' /> </label> <input type='file' id={inputUniqueId} onChange={props.onChange} /> </div> </> ) }
方案3:父组件传递唯一id参数
父组件渲染时给每个子组件传入唯一标识作为id:
// 父组件修改 const ParentComponent = () => { return( <ChildComponent id="upload-btn-1" onChange={function1} /> <ChildComponent id="upload-btn-2" onChange={function2} /> ) }
子组件接收参数绑定到对应元素:
const ChildComponent = (props) => { return( <> <div className='button'> <label htmlFor={props.id}> <FontAwesomeIcon icon={faImage} color='#3B5998' size='5x' /> </label> <input type='file' id={props.id} onChange={props.onChange} /> </div> </> ) }
内容的提问来源于stack exchange,提问作者ASIF KAIF
相关产品推荐
相关产品推荐

