scalajs-react中如何基于父组件动态信息修改子组件按钮状态
React / scalajs-react 父子组件状态同步实现方案
核心逻辑
遵循React单向数据流原则,采用父组件持有状态、通过props透传状态、子组件直接基于props派生UI的惯用方案,全程保证单一数据源,避免状态不同步问题。
原生React实现示例
// 子组件:直接接收父组件传的状态I作为props,不需要内部维护冗余状态 const ChildButton = ({ infoI }) => { // 直接根据infoI计算按钮状态,比如长度小于3时禁用 const isDisabled = infoI.length < 3 return <button disabled={isDisabled}>提交</button> } // 父组件:持有动态状态infoI const Parent = () => { const [infoI, setInfoI] = useState('') return ( <div> <input value={infoI} onChange={e => setInfoI(e.target.value)} /> {/* 把动态状态传给子组件 */} <ChildButton infoI={infoI} /> </div> ) }
scalajs-react 实现示例
import japgolly.scalajs.react._ import japgolly.scalajs.react.vdom.html_<^._ // 子组件Props定义,接收父组件传的状态I case class ChildButtonProps(infoI: String) val ChildButton = ScalaFnComponent[ChildButtonProps] { props => // 直接基于props的infoI派生按钮状态 val isDisabled = props.infoI.length < 3 <.button(^.disabled := isDisabled, "提交") } // 父组件实现 val Parent = ScalaFnComponent.withHooks[Unit] .useState("") // 持有动态状态infoI .render { (_, infoI) => <.div( <.input( ^.value := infoI.value, ^.onChange ==> ((e: ReactEventFromInput) => infoI.setState(e.target.value)) ), ChildButton(ChildButtonProps(infoI.value)) ) }
特殊场景补充
如果子组件内部存在需要和父状态I联动的私有状态(比如按钮点击后的倒计时状态需要在I变化时重置),可以在子组件中通过useEffect监听props的I变化,同步更新内部状态:
// scalajs-react 示例 val ChildButton = ScalaFnComponent.withHooks[ChildButtonProps] .useState(false) // 子组件私有状态:是否处于点击后倒计时 .useEffectBy(_.props.infoI) { props => // 监听infoI变化触发回调 // infoI变化时重置倒计时状态 _.setState(false) } .render { (props, countingDown) => val isDisabled = props.infoI.length < 3 || countingDown.value <.button(^.disabled := isDisabled, if(countingDown.value) "请稍候" else "提交") }
注意事项
- 不要在子组件中将props的I仅作为初始值赋值给内部state后就不再同步,会导致父状态更新后子组件UI不更新
- 优先选择直接基于props派生UI的方式,仅当存在子组件私有联动状态时才需要用
useEffect做同步 - 所有按钮状态(禁用、文案、样式)的计算逻辑如果是通用的,可以放在父组件统一处理后再传给子组件,也可以放在子组件内部处理,根据业务场景判断即可
内容的提问来源于stack exchange,提问作者Mandroid
相关产品推荐
相关产品推荐

