我是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>
)}
答案 0 :(得分:3)
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>
答案 1 :(得分:1)
之所以会发生这种情况,是因为useState
钩子不是“钩”到您的SearchComponent
而是您的MyInput
组件。每当调用updateCitySearch()
时,您都会更改MyInput
的状态,从而迫使 entire 组件重新呈现。
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()
,应用组件将重新呈现,并且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>
);
}
答案 2 :(得分:0)
我也是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>
);
}