简体   繁体   中英

call child methods from parent of a component rendered using a map function in react native

am building a form which insert fields depending on the json definition of the field the json object is parsed and passed on to a switch statement which select an appropriate widget and insert it into an array this array is sorted then rendered using array map what i need to achieve is to call a validate field of each field after a submit is pressed now how can i access this elements a call the appropriate validate logic

what i have tried so far

  1. using refs when i push the widgets into the array throw error relating to assigning refs outside render function
    1. wrap the call to map within a referenced view and access the widgets as children of that view via this.refs["myWrapper].props.children this approach give me access to my widgets but the objects returned doesn't contain my methods so calling them throw error for not a function

code sample

`export class myForm extends Component{

constructor(props){
    super(props);
    this.fields=[];
}

getFields(fields){

 let {formName,title}=this.props;

    let field,_fields=[],item;

    fields= this.sortFieldsOrder(fields);


    fields.forEach((sect,i)=>{
        for(field in sect)
        {
            item=sect[field];
            switch (item.widget){

                case "inlineText":
                    _fields.push(
                        <EbTextInput  key={field}

                                     {...{...item.props,formName,title}}
                                     field={field}
                                     label={item.hasOwnProperty("label")?item.label:""}
                                     validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
                        />
                    );

                    break;
                case "hidden":

                    _fields.push(
                        <EbHiddenInput  key={field}
                                       {...{...item.props,formName,title}}
                                       field={field}
                                       label={item.hasOwnProperty("label")?item.label:""}
                                       validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
                        />
                    );
                    break;
                case"modal":
                    _fields.push(

                        <EbModalInput
                                      key={field}
                                      {...{...item.props,formName,title}}
                                      field={field}
                                      fields={item.props.fields instanceof Array?this.getFields(item.props.fields):[]}
                                      label={item.hasOwnProperty("label")?item.label:""}
                                      validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
                        />

                    );
                    break;
                case"filePicker":

                  let  picker=<EbFilePickerInput key={field}
                                                 {...{...item.props,formName,title}}
                                                 field={field}
                                                 label={item.hasOwnProperty("label")?item.label:""}
                                                 validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
                  />;
                    picker=[picker];

                    _fields.push(
                        <EbModalInput  key={field}
                                      {...{...item.props,formName,title}}
                                      field={field}
                                      fields={picker}
                                      label={item.hasOwnProperty("label")?item.label:""}
                                      validator={item.hasOwnProperty("validator")?item.validator:()=>{}}
                        />
                    );
                    break;
                case "option":
                    _fields.push(
                        <EbOptionInput

                            key={field}
                            {...{...item.props,formName,title}}
                            field={field}
                            fields={item.props.fields instanceof Array?this.getFields(item.props.fields):[]}
                            label={item.hasOwnProperty("label")?item.label:""}
                            validator={item.hasOwnProperty("validator")?item.validator:()=>{}}                            />
                    );
                    break;
                default:

            }


        }
    });
    return _fields;
}
sortFieldsOrder(arr){
    return  arr.sort((a,b)=>{
        let keyA=Object.keys(a)[0];
        let keyB=Object.keys(b)[0];
        if(a[keyA]["order"]<b[keyB]["order"])return 1;
        if(a[keyA]["order"]>b[keyB]["order"])return -1;
        return 0;
    });
}
componentWillMount(){

    let {fields}=this.props;
    this.fields=this.getFields(fields)

}
renderFields(){
   return this.fields.map((item)=>{
        return item;
    })
}
validateForm(){
    let field;
    let fields=this.refs["wrapper"].props.children;
    let status=true;
    React.Children.map(this.refs["wrapper"].props.children, (child) => {
        if(!child.validate()){
            status= false;
            console.log("valid form cheki");
            // break;
        }
    })



   return status;
}
render(){
    return(
        <View ref="wrapper" style={[styles.flex1]}>
            {this.renderFields()}
            <Button text="Submit" onPress={(e)=>{
                if(this.validateForm()){
                    //alert("valid form")
                }
                else
                    alert("invalid form")
            }}> </Button>
        </View>)
}

}

`

在反应中,无论出于何种原因,它都是蚂蚁模式直接访问节点,所以我决定使用redux遵循上面的第一个注释,我可以发送一个验证信号,并让每个小部件验证其自己的状态,这减少了耦合,易于实现和调试所以我建议每个有相同问题的人都遵循此通行证

Actually you can use refs in your case, but instead of generating children components by calling getFields in componentWillMount , you'd better call it directly in render method. In other words, there's no need to have a this.fields , you can render them directly. As long as you have correct keys, React will manage the cache properly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM