ReactJS中能否获取MobX observable变量的引用以直接修改其值?
JavaScript 没有 C 语言那种直接操作内存地址的指针能力,也不需要通过这种方式修改 observable 值,以下是两种符合 MobX 设计逻辑的实现方案,可以做到只写一次通用逻辑,不需要为每个字段单独编写更新函数:
方案1:统一管理表单字段 + 通用更新action
把所有表单字段放到同一个 observable 对象中,仅编写一个通用的更新函数,子组件通过字段名触发更新即可,这是最常用的实现方式:
父组件改造
@observer class Exemple extends React.Component { // 所有表单字段统一放在一个observable对象中管理 @observable formData = { Nom: '', // 后续新增字段直接加在这里即可,不需要写新的更新函数 Prenom: '', Age: '' } // 通用更新action,全局只需要写一次 @action updateFormField = (fieldName, newValue) => { this.formData[fieldName] = newValue } render() { return ( <FormComponent ContainerStyle={{ display: 'flex', flexDirection: 'row', flexWrap: 'wrap', }} ObjArray={[ { InputDivStyle: { width: '49%', marginRight: '2%' }, FieldType: 'textInput', FieldStyle: { borderColor: this.missingLastName ? 'red' : COLOR_NOT_BLACK }, fieldName: 'Nom', // 绑定对应的字段名 Placeholders: 'Ex. Durand', Value: this.formData.Nom, InputTitle: 'Nom', }, // 新增字段只需要加配置项,不需要额外写更新逻辑 { InputDivStyle: { width: '49%' }, FieldType: 'textInput', fieldName: 'Prenom', Placeholders: 'Ex. Jean', Value: this.formData.Prenom, InputTitle: 'Prénom', } ]} onFieldChange={this.updateFormField} // 把通用更新函数传给子组件 /> ) } }
子组件改造
@observer class FormComponent extends React.Component<props> { render() { const { ObjArray, ContainerStyle, onFieldChange } = this.props return ( <div style={ContainerStyle}> {ObjArray.map((e, index: number) => { const { Disabled, FieldStyle, InputDivStyle, FieldType, Placeholders, fieldName, Value, InputTitle } = e return ( <div style={InputDivStyle ?? {}} key={index + 'Input'}> {InputTitle && <Label medium>{InputTitle}</Label>} <GenericInput disabled={Disabled ?? false} placeholder={Placeholders ?? ''} style={FieldStyle ?? {}} type={FieldType ?? ''} value={Value ?? ''} onChange={evt => { // 调用通用更新函数,传入字段名和新值即可 onFieldChange(fieldName, evt.target.value) }} /> </div> ) })} </div> ) } } export default FormComponent
方案2:使用observable.box实现类“指针”效果
如果你不想把字段都整合到同一个对象中,可以用 MobX 提供的 observable.box 包装原始类型值,返回的是引用类型的observable对象,子组件拿到引用后可以直接修改值,效果和你想要的“指针”逻辑一致:
父组件改造
import { observable } from 'mobx' @observer class Exemple extends React.Component { // 用observable.box包装原始类型,返回引用类型的observable对象 Nom = observable.box('') Prenom = observable.box('') render() { return ( <FormComponent ContainerStyle={{ display: 'flex', flexDirection: 'row', flexWrap: 'wrap', }} ObjArray={[ { InputDivStyle: { width: '49%', marginRight: '2%' }, FieldType: 'textInput', FieldStyle: { borderColor: this.missingLastName ? 'red' : COLOR_NOT_BLACK }, observableBox: this.Nom, // 直接传observable对象的引用 Placeholders: 'Ex. Durand', Value: this.Nom.get(), // 取值用.get()方法 InputTitle: 'Nom', }, { InputDivStyle: { width: '49%' }, FieldType: 'textInput', observableBox: this.Prenom, Placeholders: 'Ex. Jean', Value: this.Prenom.get(), InputTitle: 'Prénom', } ]} /> ) } }
子组件改造
@observer class FormComponent extends React.Component<props> { render() { const { ObjArray, ContainerStyle } = this.props return ( <div style={ContainerStyle}> {ObjArray.map((e, index: number) => { const { Disabled, FieldStyle, InputDivStyle, FieldType, Placeholders, observableBox, Value, InputTitle } = e return ( <div style={InputDivStyle ?? {}} key={index + 'Input'}> {InputTitle && <Label medium>{InputTitle}</Label>} <GenericInput disabled={Disabled ?? false} placeholder={Placeholders ?? ''} style={FieldStyle ?? {}} type={FieldType ?? ''} value={Value ?? ''} onChange={evt => { // 直接通过引用修改observable的值,不需要额外传更新函数 observableBox.set(evt.target.value) }} /> </div> ) })} </div> ) } } export default FormComponent
注意:JavaScript中原始类型(字符串、数字、布尔值等)都是值传递,直接把
this.Nom这类原始值传给子组件时,子组件拿到的只是值的拷贝,修改拷贝不会影响父组件的原始变量,必须通过引用类型或者回调函数的方式实现跨组件的状态修改。
内容的提问来源于stack exchange,提问作者cricciardi
相关产品推荐
相关产品推荐

