Ed of the Mountain
Ed of the Mountain

Reputation: 5459

How to pass a read write datasource item from parent to child view in react-native?

Using react-native, how can a parent view, pass a read-write object to a child view, where it can be modified, then have the parent view re-render when the child returns to the parent view?

I have a WaypointList ListView in a navigator. When user selects a row, the DetailView displays TextInput's for editing.

// The Parent "Master View"
var WaypointList = React.createClass({

  getInitialState: function() {
    var ds = new ListView.DataSource({
      rowHasChanged: (r1, r2) => r1 !== r2
    });

    return {
      itemList: this._genRows(),
      dataSource: ds.cloneWithRows(this._genRows()),
      editEnabled: false,
      planLocked: false,
      selectionCount: 0,
      unitType: 0,
    };
  },

  // ToDo: Turn this into a real database datasource
  _genRows: function(): Array < any > {
    var arrayList = [];
    var waypoint = new Waypoint('Waypoint1', 0.0, 0.0, 10, true);
    arrayList.push(waypoint);
    waypoint = new Waypoint('Waypoint2', 20.0, 4.0, 10, true);
    arrayList.push(waypoint);
    return arrayList;
  },

  getDataSource: function(waypoints: Array < any > ): ListView.DataSource {
    return this.state.dataSource.cloneWithRows(waypoints);
  },

  selectRow: function(waypoint: Object) {
    this.props.navigator.push({
      title: waypoint.name,
      component: WaypointScreen,
      passProps: {
        waypoint: waypoint,
      },
    });
  },
});

// The Child "Detail View"
// How can I modify an object passed into the "Detail View"
// passProps appears to be read-only ?
var DetailView = React.createClass({

      textInputValue: null,

      getInitialState: function() {
        console.log('name:', this.props.person.name);
        console.log('age:', this.props.person.age);
        return {
          textDistance: this.props.waypoint.distance.meters.toString(),
          textDepth: this.props.waypoint.depth.meters.toString(),
        };
      },

      render: function() {
          return ( < View style = {
                {
                  flexDirection: 'row',
                  justifyContent: 'center'
                }
              } >
              < TextInput style = {
                styles.textInput
              }
              ref = 'distance1'
              placeholder = "Enter meters"
              editable = {
                isEditable
              }
              keyboardType = "decimal-pad"
              returnKeyType = 'next'
              onChangeText = {
                (text) => {
                  text = text.replace(/\D/g, '');
                  var meters = parseFloat(text);
                  this.setState({
                    textDistance: text
                  });
                }
              }
              value = {
                this.state.textDistance
              }
              onSubmitEditing = {
                (event) => {
                  this.refs.depth1.focus();
                }
              }
              />

      <View style={styles.separatorHorizontal} / >
              < /View>

    );
  },
});

I started learning react-native about 2 weeks ago yet I am no closer to figuring out a solution.

Are passProps only for read-only information?

How can read-write modification of a datasource be achieved?

Thanks in advance.

Any tips or direction are much appreciated,

-Ed

Upvotes: 0

Views: 296

Answers (1)

Nader Dabit
Nader Dabit

Reputation: 53711

You need to set the state in the parent, and pass that state down as props to the child. When the child element changes to the new value you need, you set a callback function to the parent that resets the parent state, which in turn resets the props of any children using that value.

Check out this very basic example:

https://rnplay.org/apps/huQTKA

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TextInput
} = React;

var Parent = React.createClass({

  getInitialState() {
        return { text: '' }
    },

  onChange(text){
    this.setState({ text })
  },

  render() {
    return (
      <View style={styles.container}>
        <Text>Hello, { this.state.text }</Text>
        <Child text={ this.state.text } onChange={ this.onChange } />
     </View>
    );
  }
});       

var Child = React.createClass({
  render() {
    return (
      <View style={styles.container2}>
        <TextInput onChangeText={ (text) => this.props.onChange(text) } style={ styles.textInput }  />
        <Text>{ this.props.text }</Text>
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop:50
  },
  container2: {
    marginTop:25
  },
  textInput: {
    height: 60,
    backgroundColor: '#efefef',
    borderBottomWidth: 1,
    borderBottomColor: '#ededed',
    marginTop:13,
    marginBottom:13
  }
});

AppRegistry.registerComponent('Parent', () => Parent);

Upvotes: 1

Related Questions