简体   繁体   English

反应子组件不获取道具和更新状态

[英]React child component not fetching props and updating state

I have a form that uses a child component with input fields.我有一个使用带有输入字段的子组件的表单。 I have used props to get the data from the parent component, but it's not adding the prop value to the input field.我已经使用 props 从父组件获取数据,但它没有将 prop 值添加到输入字段。 There is no errors in the console.控制台中没有错误。

Parent component:父组件:

const {
  address,
  errors
} = this.state;

return (
    <form noValidate autoComplete="off" onSubmit={this.onSubmit.bind(this)}>
     <LocationInputGroup
        errors={errors}
        address={address}
     />

     <Button
        type="submit"
        style={{ marginRight: 10, marginTop: 20 }}
        variant="callToAction"
    > Submit</Button>
    </form>
);

Child component:子组件:

constructor(props) {
  super(props);

  this.state = {
     address: "",
     errors: {}
  };
}

componentDidMount() {
        this.setState({
            errors: this.props.errors,
            address: this.props.address
        });
}

render() {
  const {
    address,
    errors
  } = this.state;
  return (
    <div>
      <InputGroup
        value={address}
        error={errors.address}
        label="Address"
        name={"address"}
        onChange={e => this.setState({ address: e.target.value })}
        placeholder={"Address"}
      />
    </div>
  );
}

InputGroup component:输入组组件:

class InputGroup extends Component {
    constructor(props) {
        super(props);
    }

    //TODO check if scrolling still changes with number inputs
    //Bug was in Chrome 73 https://www.chromestatus.com/features/6662647093133312
    //If it's no longer a bug these listeners can be removed and the component changed back to a stateless component
    handleWheel = e => e.preventDefault();

    componentDidMount() {
        if (this.props.type === "number") {
            ReactDOM.findDOMNode(this).addEventListener("wheel", this.handleWheel);
        }
    }

    componentWillUnmount() {
        if (this.props.type === "number") {
            ReactDOM.findDOMNode(this).removeEventListener("wheel", this.handleWheel);
        }
    }

    render() {
        const {
            disabled,
            classes,
            error,
            value,
            name,
            label,
            placeholder,
            type,
            isSearch,
            onChange,
            onBlur,
            onFocus,
            multiline,
            autoFocus,
            InputProps = {},
            autoComplete,
            allowNegative,
            labelProps
        } = this.props;

        if (type === "phone") {
            InputProps.inputComponent = PhoneNumberInputMask;
        }

        let onChangeEvent = onChange;
        //Stop them from entering negative numbers unless they explicitly allow them
        if (type === "number" && !allowNegative) {
            onChangeEvent = e => {
                const numberString = e.target.value;
                if (!isNaN(numberString) && Number(numberString) >= 0) {
                    onChange(e);
                }
            };
        }

        return (
            <FormControl
                className={classes.formControl}
                error
                aria-describedby={`%${name}-error-text`}
            >
                <FormatInputLabel {...labelProps}>{label}</FormatInputLabel>
                <TextField
                    error={!!error}
                    id={name}
                    type={type}
                    value={value}
                    onChange={onChangeEvent}
                    margin="normal"
                    onBlur={onBlur}
                    onFocus={onFocus}
                    InputProps={{
                        ...InputProps,
                        classes: {
                            input: classnames({
                                [classes.input]: true,
                                [classes.searchInput]: isSearch
                            })
                        }
                    }}
                    placeholder={placeholder}
                    multiline={multiline}
                    autoFocus={autoFocus}
                    disabled={disabled}
                    autoComplete={autoComplete}
                    onWheel={e => e.preventDefault()}
                />

                <FormHelperText
                    className={classes.errorHelperText}
                    id={`${name}-error-text`}
                >
                    {error}
                </FormHelperText>
            </FormControl>
        );
    }
}

InputGroup.defaultProps = {
    value: "",
    type: "text",
    labelProps: {}
};

InputGroup.propTypes = {
    error: PropTypes.string,
    value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    name: PropTypes.string.isRequired,
    label: PropTypes.string,
    placeholder: PropTypes.string,
    type: PropTypes.string,
    isSearch: PropTypes.bool,
    onChange: PropTypes.func.isRequired,
    onBlur: PropTypes.func,
    onFocus: PropTypes.func,
    multiline: PropTypes.bool,
    autoFocus: PropTypes.bool,
    InputProps: PropTypes.object,
    disabled: PropTypes.bool,
    autoComplete: PropTypes.string,
    allowNegative: PropTypes.bool,
    labelProps: PropTypes.object
};

export default withStyles(styles)(InputGroup);

I hope someone can advise what the issue is and how to overcome it.我希望有人可以建议问题是什么以及如何克服它。

Normally when we pass data from parent, we consider it to be Immutable , (ie) It should not be changed directly from the child components .通常,当我们从父组件传递数据时,我们认为它是不可变的(即)不应直接从子组件更改

So, what one could do is use the prop value directly from the parent and use a method to mutate or change from the parent .因此,人们可以做的是直接从父级使用 prop 值,并使用一种方法从父级进行变异或更改

Below code is self explanatory.下面的代码是不言自明的。

Parent家长

class Parent {

  // parent immutable state
  public parentObject: object = {
     location: "",
     phoneNo: ""
  };

  constructor() {
    this.state = {
       parentObject: this.parentObject
    }
  }


  public onParentObjectChangeCallBack(key: string, value: string | number) {
    this.state.parentObject[key] = value;
    // to rerender
    this.setState();
  }

  public render () {
    return <ChildComponent parentObject={this.state.parentObject} 
           onChange={this.onParentObjectChangeCallBack} />
  }

}

Child孩子

class ChildComponent {
  @Prop
  public parentObject: object;

  @Prop
  public onChange: Function;

  public render() {
     <div>
        {
          this.parentObject.keys.map((key) => {
            return <div>
                     <span> {{key}}</span>
                     // calls parent method to change the immutable object
                     <input value={{this.parentObject[key]}} onChange=(val) => 
                            this.onChange(key, val) />
                   </div>
          })
        }
     </div>


  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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