React条件渲染触发DOM元素不识别props警告的问题求助
act_devtools_backend.js:2655 Warning: React does not recognize the
isDefaultprop on a DOM element. If you intentionally want it to appear in the DOM as a custom attribute, spell it as lowercaseisdefaultinstead. If you accidentally passed it from a parent component, remove it from the DOM element.
在给代码加入IsTermsAndConditionsEnabled条件渲染逻辑后,向DateInput组件传入fmoId、isDefault、isAdmin属性时触发上述React警告。移除该条件渲染后警告消失,尝试用&&运算符解决无效。
相关代码
父组件条件渲染片段
{IsTermsAndConditionsEnabled ? <> <DateInput id="PublishDate" label="Publish date" fmoId={fmoId} isDefault={isDefault} isAdmin={isAdmin} defaultValue={defaultValues && defaultValues.PublishDate.value} textValue={selectedFmoValues && selectedValues.PublishDate.value} resourceId={selectedFmoValues && selectedValues.PublishDate.resourceId} /> <Editor id="SomeId" label="Some Label" /> </> : <span></span> }
DateInput组件代码
import React, { useState, useEffect } from "react"; import { InputLabel, InputBase } from "@material-ui/core"; import LightToolTip from "./../LightToolTip"; const DateInput = ({ id, label, fmoId, isDefault, isAdmin, defaultValue, textValue, resourceId, updateParentValue, }) => { const [inputVal, setInputVal] = useState(""); const today = new Date().setUTCHours(0, 0, 0, 0); useEffect(() => { setInputVal(textValue || "") }, [fmoId, textValue]); const updateInputVal = (value) => { const calendarDate = new Date(value).setUTCHours(0,0,0,0); if (calendarDate >= today) { setInputVal(value); updateParentValue(id, value, resourceId, false); } }; function getValidFormat(inputDate) { const trimedDate = inputDate.trim(); if (trimedDate.length > 0) { const inputDate = new Date(trimedDate); const year = inputDate.getFullYear(); const month = String(inputDate.getMonth() + 1).padStart(2, '0'); const day = String(inputDate.getDate()).padStart(2, '0'); const formattedDate = `${year}-${month}-${day}`; return formattedDate; } return ""; } return ( <> <LightToolTip title={!isAdmin ? "" : `Key: ${id}`}> <InputLabel htmlFor={id}> {label} </InputLabel> </LightToolTip> { !isDefault ? ( <LightToolTip title={`Default: ${defaultValue || "No Default Found"}`}> <InputBase type="date" min={today} fullWidth={true} id={id} name={id} value={getValidFormat(inputVal)} onChange={(e) => updateInputVal(e.target.value)} /> </LightToolTip> ) : <InputBase type="date" min={today} fullWidth={true} id={id} name={id} value={getValidFormat(inputVal)} onChange={(e) => updateInputVal(e.target.value)} /> } </> ); }; export default DateInput;
已尝试的解决方法
- 使用
&&运算符,无效果; - 移除条件渲染代码,警告消失。
问题原因及解决方案
原因
React为优化性能会复用相同类型的DOM节点。你的条件渲染中,false分支是<span>元素,true分支是包含DateInput的片段,当状态切换时,React会尝试复用原本的<span>节点作为DateInput内部的DOM元素(如InputBase),导致传给DateInput的自定义prop意外附加到了这个DOM元素上,触发警告。
解决方案
方案1:给条件分支添加唯一key属性,强制React创建新元素
修改父组件代码,给两个分支分别添加唯一key,避免DOM节点复用:
{IsTermsAndConditionsEnabled ? <React.Fragment key="terms-enabled"> <DateInput id="PublishDate" label="Publish date" fmoId={fmoId} isDefault={isDefault} isAdmin={isAdmin} defaultValue={defaultValues && defaultValues.PublishDate.value} textValue={selectedFmoValues && selectedValues.PublishDate.value} resourceId={selectedFmoValues && selectedValues.PublishDate.resourceId} /> <Editor id="SomeId" label="Some Label" /> </React.Fragment> : <span key="terms-disabled"></span> }
方案2:将空分支替换为空Fragment
把false分支的<span></span>换成空的Fragment,让React没有可复用的DOM节点:
{IsTermsAndConditionsEnabled ? <> <DateInput // 保持原有props /> <Editor id="SomeId" label="Some Label" /> </> : <></> }
内容的提问来源于stack exchange,提问作者Hakuna

