Pass data between two components in React Native

2019-07-27 15:35发布

问题:

I have a component that encapsulates three components one of them is the DrawerLayoutAndroid. Now I want to pass the reference of the drawer from the drawer component to the main component and then pass it to the header component so I can trigger it from the header component.

I have no idea how to do that.

Here is the main component 'cases.js'

import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import Header from '@components/header';
import BottomBar from '@components/bottom-bar';
import SideBar from '@components/drawer';

export default class Cases extends Component {

  state = {
    title : 'Cases'
  }

  change_text = () => {

    this.setState({ title : 'Test' })

  }

  open_drawer = (ref) => {

    ref.openDrawer();

  }

  close_drawer = (ref) => {

    ref.closeDrawer();

  }

  render() {

    return (

      <SideBar style={ styles.container }>

        <Header title={ this.state.title } change_text={ this.change_text } open={ this.state.side_bar } />

        <View style={ styles.body }>

          <Text style={ styles.text }> { this.state.name } </Text>

          <TouchableOpacity onPress={ () => this.change_text() } style={ styles.button }>

            <Text> Change State </Text>

          </TouchableOpacity>

        </View>

        <BottomBar ref={ this.state.side_bar } />

      </SideBar>

    )

  }

}

const styles = StyleSheet.create({
  container : {
    flex : 1,
    flexDirection: 'column',
  },
  body : {
    flex : 1,
    backgroundColor: '#ccc',
    justifyContent: 'center',
    alignItems: 'center'
  },
  text : {
    color : '#fff'
  },
  button : {
    backgroundColor : '#eee',
    paddingVertical: 5,
    paddingHorizontal: 10
  }
})

Here is my header:

import React, { Component } from 'react';
import { View, Text, StyleSheet, TouchableOpacity, Image } from 'react-native';
import DrawerLayoutAndroid from 'DrawerLayoutAndroid';
import LinearGradient from 'react-native-linear-gradient';

export default class Header extends Component {

  change_text = () => {

    this.props.change_text();

  }

  open = ()

  render () {

    return (

      <LinearGradient start={{x: 0, y: 0}} end={{x: 1, y: 0}} colors={['#a4d294', '#3ac6f3']} style={ styles.header }>

          <TouchableOpacity onPress={ () => this.props.change_text() }>

            <Image source={ require('@media/images/add.png') } style={ styles.add_button } />

          </TouchableOpacity>

          <Text style={ styles.title }> { this.props.title } </Text>

          <TouchableOpacity onPress={ () => this.props.open() }>

            <Image source={ require('@media/images/more.png') } style={ styles.more_button } />

          </TouchableOpacity>

      </LinearGradient>

    )

  }

}

const styles = StyleSheet.create({
  header : {
    height: 70,
    backgroundColor: '#eee',
    flexDirection: 'row',
    justifyContent: 'space-between',
    alignItems: 'center'
  },
  title : {
    color : '#fff',
    textAlign: 'center',
    fontSize: 20,
    letterSpacing: 3
  },
  add_button : {
    width: 30,
    height: 30,
    marginHorizontal: 10
  },
  more_button : {
    width: 30,
    height: 30,
    marginHorizontal: 10
  }
})

And here is my drawer.js

import React, { Component } from 'react';
import { View, Text } from 'react-native';
import DrawerLayoutAndroid from 'DrawerLayoutAndroid';
import LinearGradient from 'react-native-linear-gradient';

export default class Drawer extends Component {

  render () {

    const NavigationMenu = (
      <LinearGradient start={{x: 0, y: 0}} end={{x: 0, y: 1}} colors={['#a4d294', '#3ac6f3']} style={{ flex: 1 }}>
        <View style={{ flex : 6, justifyContent: 'center' }}>
          <Text>He There</Text>
        </View>
      </LinearGradient>
    )

    return (

      <DrawerLayoutAndroid
        drawerWidth={250}
        drawerPosition={ DrawerLayoutAndroid.positions.Right }
        renderNavigationView={ () => NavigationMenu }
        ref={ (drawer) => this.props.ref = drawer }
      >

        { this.props.children }

      </DrawerLayoutAndroid>

    )

  }

}

回答1:

I am going to answer your question by giving a simple example. Lets take 2 components parent and child. You want to pass some message from parent to child and get a callback from child to parent when an event occurs in child.

export default class Parent extends React.Component<any, any> {

  callback (paramFromChild) => {
    // implement what to do when certain event occurs in child component
  }

  render () {
    <View>
       <Child message={"some text"} callbackFromChild={this.callback}/>
    </View>
  }
}

Child component

Interface childProps {
   message: string

   callbackFromChild(paramFromChild);
}

export default class Child extends React.Component<childProps, any> {

  render () {
    <View>
       <Button title={this.props.message} onPress={this.props.callbackFromChild("some message from child")}/>
    </View>
  }
}

In this way you can communicate between different components using props.