更改子组件后将数据传递给父组件

时间:2019-01-28 13:10:39

标签: javascript reactjs react-native

我想创建一个自定义选择器组件,我想在每次状态更改后将数据传递给父级,我尝试在render方法中使用this.props.onChange并传递要在父级中使用的状态。 当我使用consol.log时,它会记录我想要的值,但是当我使用时 value=> this.setState({value})我收到此错误:

Unhandled JS Exception: Invariant Violation: Invariant Violation: Maximum update depth exceeded.

这是我的代码:

export default class DatePicker extends React.Component {


    state = {
        days:31,
        month: 1,
        day : 1,
        year : 9500
    };



    render() {
        const {day, month, year} = this.state

        this.props.onChange({day,month, year})
        return(

               <View style={{flex:1 ,flexDirection:'row'}}> 

               <Picker
                         selectedValue={this.state.year}
                         enabled={false}
                         style={{height: 10, width: 70}}
                         onValueChange={(itemValue, itemIndex) =>
                             this.setState({year: itemValue})
                         }>
                        {[...Array(12).keys()].map(i => <Picker.Item label={(i+9500).toString()} value={i+9500} /> )}

                         </Picker>

                         <Picker
                         selectedValue={this.state.text}
                         enabled={false}
                         style={{height: 0, width: 70}}
                         onValueChange={(itemValue, itemIndex) =>
                             this.setState({text: itemValue, days: itemValue < 6? 31 : 30 })
                         }>
                         {date.map(i => <Picker.Item label={i.label} value={i.value} /> )}

                         </Picker>
                         <Picker
                         selectedValue={this.state.day}
                         enabled={false}
                         style={{height: 10, width: 70}}
                         onValueChange={(itemValue, itemIndex) =>
                             this.setState({day: itemValue})
                         }>
                        {[...Array(this.state.days).keys()].map(i => <Picker.Item label={(i+1).toString()} value={i+1} /> )}

                         </Picker>

                         </View>

        )

    }
}

TL; DR

我想创建一个具有<TextInput>之类的OnChange道具的组件,什么是最好的方法?

3 个答案:

答案 0 :(得分:0)

创建函数,该函数将处理这些值并将其传递给父级

handleOnChange = value => {
  const data = {
    ...this.state,
    ...value
  }

  this.setState(data)
  this.props.onChane(data)

}

然后在onValueChange上使用该处理程序,而不是this.setState

<Picker
   selectedValue={this.state.day}
   enabled={false}
   style={{height: 10, width: 70}}
   onValueChange={(itemValue, itemIndex) =>
   this.handleOnChange({day: itemValue})
 }>

完整的代码将是这样

export default class DatePicker extends React.Component {


state = {
    days:31,
    month: 1,
    day : 1,
    year : 9500
};

handleOnChange = value => {
  const data = {
    ...this.state,
    ...value,
  }

  this.setState(data)
  this.props.onChange(data)
}

render() {
    const {day, month, year} = this.state

    this.props.onChange({day,month, year})
    return(

           <View style={{flex:1 ,flexDirection:'row'}}> 

           <Picker
                     selectedValue={this.state.year}
                     enabled={false}
                     style={{height: 10, width: 70}}
                     onValueChange={(itemValue, itemIndex) =>
                         this.handleOnChange({year: itemValue})
                     }>
                    {[...Array(12).keys()].map(i => <Picker.Item label={(i+9500).toString()} value={i+9500} /> )}

                     </Picker>

                     <Picker
                     selectedValue={this.state.text}
                     enabled={false}
                     style={{height: 0, width: 70}}
                     onValueChange={(itemValue, itemIndex) =>
                         this.handleOnChange({text: itemValue, days: itemValue < 6? 31 : 30 })
                     }>
                     {date.map(i => <Picker.Item label={i.label} value={i.value} /> )}

                     </Picker>
                     <Picker
                     selectedValue={this.state.day}
                     enabled={false}
                     style={{height: 10, width: 70}}
                     onValueChange={(itemValue, itemIndex) =>
                         this.handleOnChange({day: itemValue})
                     }>
                    {[...Array(this.state.days).keys()].map(i => <Picker.Item label={(i+1).toString()} value={i+1} /> )}

                     </Picker>

                     </View>

    )

}

}

答案 1 :(得分:0)

保持父组件中的状态逻辑。将这些值作为道具传递给子组件。 这是一个示例:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";

class A extends React.Component {
  state = {
    a: 0
  };
  updateState = () => {
    console.log("hello");
    this.setState({
      a: this.state.a + 1
    });
  };
  render() {
    return <App val={this.state.a} updateState={this.updateState} />;
  }
}
function App(props) {
  console.log(props);
  return (
    <div className="App">
      {props.val}
      <div>
        <button onClick={props.updateState}>Increment</button>
      </div>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<A />, rootElement);

Working demo

答案 2 :(得分:-1)

在您的代码中,渲染函数循环调用,因为当您将数据传递给父对象时,父和子对象将重新渲染。您可以编写一个用于设置状态并将其传递给父级的函数,并在每个选择器的onValueChange中调用它,如下所示:

onChange = (newYear, newMonth, newDay) => {
    const {day, month, year} = this.state
    if (newYear != '') this.setState({ year: newYear }, ()=>{this.props.onChange({day, month, year})})
    if (newMonth != '') this.setState({ month: newMonth }, ()=>{this.props.onChange({day, month, year})})
    if (newDay != '') this.setState({ day: newDay }, ()=>{this.props.onChange({day, month, year})})
}

并这样称呼它:

<Picker
    onValueChange={(itemValue, itemIndex) =>
           this.onChange(itemValue, '', '')
    }>