简体   繁体   English

在React Native中通过子组件更新父组件

[英]Updating Parent Component via Child Component in React Native

I have a parent component and two child components. 我有一个父组件和两个子组件。 One of the child components is a form with an add button. 子组件之一是带有add按钮的表单。 I am able to capture the text when add button is pressed, but stuck when trying to pass that value to the parent component, update the array in parent component and re-render the view. 我可以在按下add按钮时捕获文本,但是在尝试将该值传递给父组件,更新父组件中的数组并重新呈现视图时卡住了。

Parent Component: 父组件:

var Tasks = ['Competitor Study','Content Plan','Write','Promote','Consumer Research']

//Build React Component
class MyTaskList extends Component {

render() {
    return (
      <View style={styles.container}>
         <Text style={styles.titleStyle}>
          My Tasks  
          {"\n"} 
            ({Moment().format("MMM Do YY")})
          {"\n"}
        </Text>
        <AddTask />
        {this.workitems()}
      </View>
    );
  }

  workitems() {  
   return (Tasks.map(function(workitem,i) {
    return <ListItem key={i} workitem={workitem} />
        }
      )
    );  
  }

}

Child component with the form 子组件的形式

class AddTask extends Component {

    constructor(props) {
      super(props);
      this.state = {
        enterTask: 'Enter task'
      };
    }

    onTaskTextChanged(event) {
      this.setState({ enterTask: event.nativeEvent.text });
    }

    onAddPress() {
     var newtask = this.state.enterTask;
     console.log('new task - '+newtask);
    }

    render() {
        return (
            <View style={styles.addTask}>
                   <TextInput
                    style={styles.taskInput}
                    value={this.state.enterTask}
                    onChange={this.onTaskTextChanged.bind(this)}
                    placeholder='Enter task'/>
                 <TouchableHighlight style={styles.button}
                    onPress={this.onAddPress.bind(this)}
                    underlayColor='#99d9f4'>
                    <Text style={styles.buttonText}>Add</Text>
                </TouchableHighlight>
            </View>
        );
    }
}

I would instead use state for this as using forceUpdate() is not recommended 我将为此使用状态,因为不建议使用forceUpdate()

From React docs: 从React docs:

Calling forceUpdate() will cause render() to be called on the component, skipping shouldComponentUpdate(). 调用forceUpdate()将导致在组件上调用render(),而跳过shouldComponentUpdate()。 This will trigger the normal lifecycle methods for child components, including the shouldComponentUpdate() method of each child. 这将触发子组件的正常生命周期方法,包括每个子组件的shouldComponentUpdate()方法。 React will still only update the DOM if the markup changes. 如果标记发生更改,React仍然只会更新DOM。

Normally you should try to avoid all uses of forceUpdate() and only read from this.props and this.state in render(). 通常,您应该避免使用forceUpdate(),而只能从render()中的this.props和this.state中读取。 This makes your component "pure" and your application much simpler and more efficient. 这使您的组件“纯净”,您的应用程序变得更加简单和高效。

(Based off of @1ven answer) (基于@ 1ven答案)

Parent Component: 父组件:

//Build React Component
class MyTaskList extends Component {

    constructor(props) {
        super(props);

        this.state = {
            tasks: [
                'Competitor Study',
                'Content Plan',
                'Write','Promote',
                'Consumer Research'
            ]
        } 
    }

    handleAddTask(task) {
        var newTasks = Object.assign([], this.state.tasks);
        newTasks.push(task);
        this.setState({tasks: newTasks});
    }

    render() {
        return (
            <View style={styles.container}>
                <Text style={styles.titleStyle}>
                    My Tasks  
                    {"\n"} 
                    ({Moment().format("MMM Do YY")})
                    {"\n"}
                </Text>
                <AddTask onAddTask={this.handleAddTask.bind(this)} />
                {this.workitems()}
            </View>
        );
    }

    workitems() {  
        return this.state.tasks.map(function(workitem,i) {
            return <ListItem key={i} workitem={workitem} />
        });

    }
}

Child component with the form 子组件的形式

class AddTask extends Component {
    constructor(props) {
        super(props);
        this.state = {
            enterTask: 'Enter task'
        };
    }

    onTaskTextChanged(event) {
        this.setState({ enterTask: event.nativeEvent.text });
    }

    onAddPress() {
        var newtask = this.state.enterTask;
        console.log('new task - '+newtask);
        // Providing `newtask` variable to callback.
        this.props.onAddTask(newtask);
    }

    render() {
        return (
            <View style={styles.addTask}>
                <TextInput
                    style={styles.taskInput}
                    value={this.state.enterTask}
                    onChange={this.onTaskTextChanged.bind(this)}
                    placeholder='Enter task'/>
                <TouchableHighlight style={styles.button}
                    onPress={this.onAddPress.bind(this)}
                    underlayColor='#99d9f4'>
                   <Text style={styles.buttonText}>Add</Text>
                </TouchableHighlight>
            </View>
        );
    }
}

You should provide handleAddTask callback from parent to child component: 您应该提供从父组件到子组件的handleAddTask回调:

var Tasks = ['Competitor Study','Content Plan','Write','Promote','Consumer Research']

//Build React Component
class MyTaskList extends Component {

  handleAddTask(task) {
    // When task will be added, push it to array
    Tasks.push(task);
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.titleStyle}>
          My Tasks  
          {"\n"} 
          ({Moment().format("MMM Do YY")})
          {"\n"}
        </Text>
        <AddTask onAddTask={this.handleAddTask} />
        {this.workitems()}
      </View>
    );
  }

  workitems() {  
    return (
      Tasks.map(function(workitem,i) {
        return <ListItem key={i} workitem={workitem} />
      })
    );  
  }
}

Next, you should pass task from child component to this callback: 接下来,您应该将任务从子组件传递到此回调:

class AddTask extends Component {
  constructor(props) {
    super(props);
    this.state = {
      enterTask: 'Enter task'
    };
  }

  onTaskTextChanged(event) {
    this.setState({ enterTask: event.nativeEvent.text });
  }

  onAddPress() {
    var newtask = this.state.enterTask;
    console.log('new task - '+newtask);
    // Providing `newtask` variable to callback.
    this.props.onAddTask(newtask);
  }

  render() {
    return (
      <View style={styles.addTask}>
        <TextInput
          style={styles.taskInput}
          value={this.state.enterTask}
          onChange={this.onTaskTextChanged.bind(this)}
          placeholder='Enter task'/>
        <TouchableHighlight style={styles.button}
          onPress={this.onAddPress.bind(this)}
          underlayColor='#99d9f4'>
          <Text style={styles.buttonText}>Add</Text>
        </TouchableHighlight>
      </View>
    );
  }
}

That's it. 而已。 Hope, it helps! 希望能帮助到你!

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

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