有一堆类似的问题,但我看不到一个与我的难题相匹配的问题。
我有一个react组件(径向旋钮控件 - 有点像滑块)。我想达到两个结果:
- 旋转旋钮并将旋钮值向上传递给父级以进行进一步操作。
- 从父级接收目标旋钮值并相应地更新旋钮。
- 一切都没有进入无限循环!
我已经拔掉了头发 - 但有一个似乎违反react原则的可行解决方案。
我有Knob.js作为环绕第三方旋钮组件的react组件,我有app.js作为父级。
在 Knob.js 中,我们有:
export default class MyKnob extends React.Component {
constructor(props, context) {
super(props, context)
this.state = {
size: props.size || 100,
radius: (props.value/2).toString(),
fontSize: (props.size * .2)
}
if (props.value){
console.log("setting value prop", props.value)
this.state.value = props.value
} else {
this.state.value = 25 // any old default value
}
}
为了处理来自父级 (app.js) 的更新,我在 Knob.js 中有这个:
// this is required to allow changes at the parent to update the knob
componentDidUpdate(prevProps) {
if (prevProps.value !== this.props.value) {
this.setState({value: this.props.value})
}
console.log("updating knob from parent", value)
}
然后将旋钮值的变化传递回父级,我有:
handleOnChange = (e)=>{
//this.setState({value: e}) <--used to be required until line below inserted.
this.props.handleChangePan(e)
}
这也有效,但会触发警告:
App
渲染不同的组件 ( ) 时无法更新组件 (Knob
)
render(){
return (
<Styles font-size={this.state.fontSize}>
<Knob size={this.state.size}
angleOffset={220}
angleRange={280}
steps={10}
min={0}
max={100}
value={this.state.value}
ref={this.ref}
onChange={value => this.handleOnChange(value)}
>
...
现在转到 app.js:
function App() {
const [panLevel, setPanLevel] = useState(50);
// called by the child knob component. works -- but creates the warning
function handleChangePan(e){
setPanLevel(e)
}
// helper function for testing
function changePan(e){
if (panLevel + 10>100){
setPanLevel(0)
} else {
setPanLevel(panLevel+10)
}
}
return (
<div className="App">
....
<div className='mixer'>
<div key={1} className='vStrip'>
<Knob size={150} value={panLevel} handleChangePan = {(e) => handleChangePan(e)}/>
</div>
<button onClick={(e) => changePan(e)}>CLICK ME TO INCREMENT BY 10</button>
...
</div>
所以 - 它有效 - 但我违反了react原则 - 我还没有找到另一种保持外部“旋钮值”和内部“旋钮值”同步的方法。
只是为了进一步弄乱我的脑袋,如果我在 'handleOnChange' 中删除了对父级的冒泡 - 这可能会触发 prop--> state 级联回落的变化 - 我不仅缺乏与父级的同步 - 但我还需要恢复下面的 setState,以便通过摆弄(鼠标等.._)使旋钮工作!这会产生另一个警告:
在现有状态转换期间更新...
所以卡住了。征求意见并感激地收到。长篇文章的 Apols。
handleOnChange = (e)=>{
//this.setState({value: e})
**this.props.handleChangePan(e)**
}
在另一篇文章中有人建议,应该将 setState 包装成 useEffect - 但我不知道如何做到这一点 - 更不用说这是否是正确的方法。