在 React-Native + hooks 中:从子组件连续多次更新父级的值



目标是创建一个输入组件,用户可以在其中单击一个按钮,如果按住该按钮,将多次触发操作(例如,在这里考虑一个+按钮,它将连续递增父级的值(。松开按钮时,触发停止。

下面的代码是突出显示所需的基础结构(父/子(和我面临的问题的最低代码。

问题:按下时,count值仅递增一次,尽管增幅器被多次触发。父级同时拥有count值和onChange回调(沿<TextInput>模式(

我相信这是因为incr()中的value设置为渲染时的值MyInput;只要不释放按钮,MyInput就不会重新渲染,因此增量器仍绑定到该原始value

父组件:

const Screen = ({}) => {
const [ count, setCount ] = useState(0);

const onChange = (value) => {
setCount(value);
}

return (
<View style={{ flex:1, justifyContent:'center', alignItems:'center' }}>
<Text>Parent: [{count}]</Text>
<MyInput value={count} onChange={onChange}/>
</View>
)
}

子组件:MyInput遵循<TextInput>和类似的模式,其中value由父组件拥有并通过onChange回调进行更新

export const MyInput = ({ value, onChange }) => {
const [ timer, setTimer ] = useState(null);
const incr = () => {
const nv = value + 1;
console.warn(new Date(), `nv: ${nv}`);
onChange(value + 1);
}
const onPressIn = () => {
setTimer(setInterval(incr, 10));
// or calling incr() twice here, would have the same effect
};
const onPressOut = () => {
clearInterval(timer);
};
return (
<View>
<Text>Child: {value}</Text>
<TouchableOpacity
onPressIn={onPressIn}
onPressOut={onPressOut}>
<Text>+</Text>
</TouchableOpacity>
</View>
)
};

如果我使用值的本地状态副本(例如[ localValue, setLocalValue ] = useState(value)MyInput中使用setLocalValue(xxx => xxx+1),我可以部分解决这种情况......但是,它只会更新本地值,而不会更新父值。

也许强制刷新也是一个(糟糕的(选择?

我尝试了使用回调/...但是,看起来,我需要在重新渲染父级(或类似的东西(之前释放按钮。

约束条件是:功能组件和钩子以及父级拥有的value/onChange道具

知道我该如何解决上述情况吗? 提前感谢您的任何提示

import {useEffect}from 'react'
export const MyInput = ({ value, onChange }) => {
const [timer, setTimer] = useState(null);
const incr = () => {
const nv = value + 1;
// console.warn(new Date(), `nv: ${nv}`);
onChange(value + 1);
}
useEffect(() => {
incr()
setTimer(setInterval(incr, 10));
}, [value])
const onPressIn = () => {
// setTimer(setInterval(incr, 10));
// or calling incr() twice here, would have the same effect
onChange(value + 1);
};
const onPressOut = () => {
clearInterval(timer);
};
return (
<View>
<Text>Child: {value}</Text>
<TouchableOpacity
onPressIn={onPressIn}
onPressOut={onPressOut}>
<Text>+</Text>
</TouchableOpacity>
</View>
)
};

相关内容

  • 没有找到相关文章

最新更新