当我更新输入字段中的值时,光标移动到字段的末尾,但我希望它保持原样。可能导致这个问题的原因是什么?
window.location.href = window.location.href;
其中Input是文本输入字段的组件,getOnChange是:
<Input
type="text"
placeholder="test
name="test"
onChange={getOnChange(index)}
value={testVal}/>
然后将其转移到父组件,在那里我调度以通过Redux更新状态。我可以看到状态正在更新,但问题是光标没有停留在位,并且总是移动到文本的末尾
答案 0 :(得分:1)
如果光标跳到该字段的末尾,通常意味着您的组件正在重新安装。发生这种情况的原因可能是,父项中某处的值每次更新时关键属性都发生了更改,或者组件树中发生了更改。不看更多代码就很难分辨。防止重新安装,光标应停止跳跃。
使用此效果跟踪安装/卸载
useEffect(() => {
console.log('mounted');
return () => {
console.log('unmounted')
}
}, []);
答案 1 :(得分:1)
我遇到了同样的问题,这是由于 2 个连续的 setState 语句造成的。更改为单个 setState 解决了该问题。可能对某人有帮助。
修复前的代码:
const onChange = (val) => {
// Some processing here
this.setState({firstName: val}, () => {
this.updateParentNode(val)
})
}
const updateParentNode = (val) => {
this.setState({selectedPerson: {firstName: val}})
}
修复后的代码
const onChange = (val) => {
// Some processing here
this.updateParentNode(val)
}
const updateParentNode = (val) => {
this.setState({selectedPerson: {firstName: val}, firstName: val})
}
答案 2 :(得分:0)
这是受控组件设计模式的缺点。我已经面对这个问题很长时间了,并且一直忍受着。但是有一种想法,我想在业余时间尝试,但最终还是没有尝试过。也许继续我的想法可以帮助您找到所需的解决方案?
<Input
type="text"
placeholder="test
name="test"
onChange={getOnChange(index)}
value={testVal}
/>
// From props.onChangeTest
const onChangeTest = (event, index) => {
// TODO: Memorize the position of the cursor
this.setState({ testVal: event.target.value })
// Because setState is asynchronous
setTimeout(() => {
// TODO:
// Programmatically move cursor back to the saved position
// BUT it must increase/decrease based on number of characters added/removed
// At the same time considering if the characters were removed before or after the position
// Theoretically do-able, but it's very mind-blowing
// to come up with a solution that can actually 'nail it'
}, 0)
}
★如果这花了太多时间,而您只想完成工作并发布应用程序,则可能要考虑使用不受控制的组件设计模式。
答案 3 :(得分:0)
您有两个选择。
将其设置为不受控制的输入(以后无法更改输入值)
使其成为适当控制的输入
这里缺少代码,所以我不能说问题出在哪里。
setState
不是问题:https://reactjs.org/docs/forms.html#controlled-components
如果在回调中使用setState
,React应该保留光标位置。
您能举一个更完整的例子吗?
testVal
是从组件外部操纵的属性吗?
答案 4 :(得分:0)
我建议使用钩子解决此问题
const Component = ({ onChange }) => {
const [text, setText] = useState("");
const isInitialRun = useRef(false);
useEffect(() => {
if (isInitialRun.current) {
onChange(text);
} else {
isInitialRun.current = true;
}
}, [text]);
// or if you want to have a delay
useEffect(() => {
if (isInitialRun.current) {
const timeoutId = setTimeout(() => onChange(text), 500);
return () => clearTimeout(timeoutId);
} else {
isInitialRun.current = true;
}
}, [text])
return (
<Input
type="text"
placeholder="test
name="test"
onChange={setText}
value={text}/>
);
}
为防止进行初始呼叫,请在未进行任何更改的情况下使用isInitialRun
答案 5 :(得分:-1)
当您通过代码动态更新输入值时,输入上的光标将被推到末尾,这似乎是您在做的,因为我可以看到value={testVal}
:)
这是使用输入掩码的字段上的常见问题!