在React JSX vs function call to present component中当涉及到函数调用或(标签)组件之间的差异时,该问题以“否”回答。
这里有一个令人困惑的示例,其中函数调用和标记之间的差异导致焦点行为的变化。我确信那里有合理的解释的React专家-不幸的是我还没有到那里;-)
这里有标记和函数调用之间带有注释差异的代码:
import React, {useState} from 'react';
function FocusRiddle() {
const [currentRow, setCurrentRow] = useState({firstName: 'Barack', lastName: 'Obama'});
// This keeps the focus correctly
return <div>{Att()}</div>;
// This loses the focus after every letter !!!
// return <div><Att /></div>;
function Att() {
return <div>
<h1>Welcome to Focus Riddle</h1>
<div>
<MyInput key={'firstName'} name={'firstName'} row={currentRow} action={updateRow}/>
</div>
<div>
<MyInput key={'lastName'} name={'lastName'} row={currentRow} action={updateRow}/>
</div>
<div>
<button onClick={() => alert(JSON.stringify(currentRow))}>Show Row</button>
</div>
</div>
}
function updateRow(name, value) {
setCurrentRow({...currentRow, [name]: value});
}
}
function MyInput({name, row, action}) {
return <input
value={row[name]}
onChange={(event) => action(name, event.target.value)}/>
}
export default FocusRiddle;
调用Att()
等效于实现常规组件,因为您刚刚声明了一个函数并在组件范围内对其进行了调用。
所以这里没有什么特别的,状态应该持续:
function FocusRiddle() {
const [currentRow, setCurrentRow] = useState({
firstName: "Barack",
lastName: "Obama",
});
function updateRow(name, value) {
setCurrentRow({ ...currentRow, [name]: value });
}
return (
<div>
<div>
<h1>Welcome to Focus Riddle</h1>
<div>
<MyInput
key={"firstName"}
name={"firstName"}
row={currentRow}
action={updateRow}
/>
</div>
<div>
<MyInput
key={"lastName"}
name={"lastName"}
row={currentRow}
action={updateRow}
/>
</div>
<div>
<button onClick={() => alert(JSON.stringify(currentRow))}>
Show Row
</button>
</div>
</div>
</div>
);
}
但是,在调用<Att/>
时会创建React Element,因为使用JSX语法是React.createElement
的糖语法。参见React.createElement
。
因此,React元素对道具的了解会在其父对象被渲染时改变并渲染。
当您输入JSX in depth并调用input
时,将渲染setCurrentRow
,并且FocusRiddle
组件unmounts(因为在每个渲染中都重新声明了Att
组件),因此您失去了焦点。