我是reactjs新手,我正在尝试从输入中读取数据。问题是当我输入符号时,我的输入失去了焦点。但只有当所有逻辑都在函数内部时。 当带有按钮和逻辑的输入位于不同的文件中时 - 它正在工作。我真的不知道为什么...
我已经使用相同的代码创建了单独的文件并将其导入到解决方案中 - 没关系。 我尝试过 onChange={handleChange} - 也失去了焦点。
export default function MyInput(){
const [citySearch, updateCitySearch] = useState();
function searchCityClick(){
alert(citySearch);
}
const SearchComponent = ()=> (
<div>
<input
value={citySearch}
onChange={(e) => updateCitySearch(e.target.value)}/>
<Button variant="contained" color="primary" onClick={searchCityClick}>
Search
</Button>
</div>
);
return(
<div>
<div>
<SearchComponent />
</div>
</div>
)}
SearchComponent
是一个功能组件,不应在另一个组件内定义。在 SearchComponent
中定义 MyInput
将导致 SearchComponent
被重新创建(而不是重新渲染),本质上它的 DOM 将被删除,然后在每次点击时添加回来。
解决方案非常简单,从
SearchComponent
中提取 MyInput
,并通过 props
对象传递函数和数据:
const { useState, useCallback } = React;
const SearchComponent = ({ citySearch, updateCitySearch, searchCityClick }) => (
<div>
<input
value={citySearch}
onChange={e => updateCitySearch(e.target.value)} />
<button onClick={searchCityClick}>Search</button>
</div>
);
const MyInput = () => {
const [citySearch, updateCitySearch] = useState('');
const searchCityClick = () => alert(citySearch);
return(
<div>
<SearchComponent
citySearch={citySearch}
updateCitySearch={updateCitySearch}
searchCityClick={searchCityClick} />
</div>
);
};
ReactDOM.render(
<MyInput />,
root
);
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
我也是 React 新手,所以对我的解释持保留态度(希望其他人可以详细说明)..我相信这与嵌套组件以及 React 如何重新渲染有关..
如果您使用
SearchComponent
作为变量,而不是匿名函数,则这将按预期工作。
我也很好奇为什么使用这样的嵌套函数(当使用 JSX 时)会导致这种行为......可能是反模式?
function MyInput() {
const [citySearch, updateCitySearch] = React.useState();
function searchCityClick() {
alert(citySearch);
}
const SearchComponent = (
<div>
<input
value={citySearch}
onChange={(e) => updateCitySearch(e.target.value)}/>
<button variant="contained" color="primary" onClick={searchCityClick}>
Search
</button>
</div>
);
return (
<div>
<div>
{SearchComponent}
</div>
</div>
);
}
let div = document.createElement("div");
div.setAttribute("id", "app");
document.body.append(div);
ReactDOM.render(<MyInput />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
即使将嵌套函数更改为“实际组件”,每次按键后焦点也会丢失(又名 onChange)..
不起作用:
function MyInput() {
const [citySearch, updateCitySearch] = React.useState();
function searchCityClick() {
alert(citySearch);
}
const SearchComponent = () => {
return (
<div>
<input
value={citySearch}
onChange={(e) => updateCitySearch(e.target.value)}/>
<button variant="contained" color="primary" onClick={searchCityClick}>
Search
</button>
</div>
);
}
return (
<div>
<div>
<SearchComponent />
</div>
</div>
);
}
发生这种情况是因为
useState
钩子不是“钩”到您的 SearchComponent
,而是您的 MyInput
组件。每当您调用 updateCitySearch()
时,您都会更改 MyInput
的状态,从而强制 整个 组件重新渲染。
SearchComponent
,在MyInput
内部明确定义。当 citySearch-state
更新时,SearchComponent
会失去焦点,因为它周围的初始 virual DOM
不再完整,而是拥有一块全新的 DOM。本质上,每次状态更新 SearchComponent
时,您都会创建一个全新的 MyInput
。
考虑以下示例:
function App() {
const [citySearch, updateCitySearch] = useState("");
console.log("rendered App again"); //always prints
const SearchComponent = () => {
console.log("rendered Search"); //always prints
const searchCityClick = () => {
alert(citySearch);
};
return (
<div>
<input
value={citySearch}
onChange={e => {
updateCitySearch(e.target.value);
}}
/>
<button onClick={searchCityClick}>Search</button>
</div>
);
};
return (
<div>
<div>
<SearchComponent />
</div>
</div>
);
}
每次更新状态时,都会触发
console.log()
,App 组件重新渲染并重新创建 SearchComponent
。每次都会渲染 myInput
的新迭代,并创建新的 SearchComponent
。
但是如果你在
useState
中定义 SearchComponent
,那么只有 SearchComponent
会在状态改变时重新渲染,从而保持原始 myInput
组件不变,而当前 SearchComponent
保持不变。
function App() {
console.log("rendered App again"); //would never print a 2nd time.
const SearchComponent = () => {
const [citySearch, updateCitySearch] = useState("");
console.log("rendered Search"); //would print with new state change
const searchCityClick = () => {
alert(citySearch);
};
return (
<div>
<input
value={citySearch}
onChange={e => {
updateCitySearch(e.target.value);
}}
/>
<button onClick={searchCityClick}>Search</button>
</div>
);
};
return (
<div>
<div>
<SearchComponent />
</div>
</div>
);
}