How to pass radio button values from a modal component to a parent component: React Native

Viewed 189

I have a modal component (Sortby.js) with a FlatList, and each list item has two radio buttons with 'asc' and 'desc' values. When a user selects a radio button, the state in the modal component is updated with the index of the list and the value of the button pressed. A user can only select one button.

When the user presses "OK" on the modal, I need to somehow get the index of the list and value of the radio button ('asc' or 'desc') sent to the parent component. How can I do this? Been stuck on this for ages now. Code is below, link to the Snack is here: https://snack.expo.dev/@steph510/send-radio-button-index-and-values-to-parent-on-modal-close

Sortby.js

import {View, Text, Modal, StyleSheet, Button, FlatList,} from "react-native";
import { RadioButton } from "react-native-paper";

export default class Sortby extends React.Component {
  constructor(props) {
    super(props);
  }

  state = { 
    selectedIndex: 0,
    radioButtonValue: 'asc',     
  };

 onRadiochange = (index, value) => {
    this.setState({ 
      radioButtonValue: value,   
      selectedIndex: index   
    });
  };

  render() {
    return (
      <Modal visible={this.props.visible} transparent={true}>
        <View style={styles.modalStyles}>       

          <View style={styles.fieldsContainer}>
            <FlatList
              data={this.props.showInGridViewList()}
              extraData={this.state}
              renderItem={(itemData) => {
                const index = itemData.index;              
                return (
                  <View style={styles.fieldItem}>
                    <Text style={styles.fieldText}>{itemData.item.text}</Text>
                    <View style={styles.radioButtonContainer}>
                    <RadioButton.Group onValueChange={value => this.onRadiochange(index, value)}>
                      <View style={styles.singleRadioButtonContainer}>
                        <Text>Asc</Text>
                        <RadioButton
                          color='#5d86d7'                        
                          value="asc"                      
                          status={ this.state.selectedIndex === index && this.state.radioButtonValue === 'asc' ? 'checked' : 'unchecked'}

                        />
                      </View>
                      <View style={styles.singleRadioButtonContainer}>
                        <Text>Desc</Text>
                        <RadioButton
                          color='#5d86d7'                        
                          value="desc"                      
                          status={ this.state.selectedIndex === index && this.state.radioButtonValue === 'desc' ?  'checked' : 'unchecked'}      
                        />
                      </View>
                      </RadioButton.Group>
                    </View>
                  </View>
                );
              }}
              alwaysBounceVertical={false}
            />
          </View>
          <View style={styles.buttonContainer}>
            <View style={styles.button}>
              <Button title="OK" color={"#5d86d7"}  onPress={this.props.onOK}></Button>         
            </View>
            <View style={styles.button}>
              <Button
                title="Cancel"
                color={"#5d86d7"}
                onPress={this.props.onCancel}
              ></Button>
            </View>
          </View>
        </View>
      </Modal>
    );
  }
}

const styles = StyleSheet.create({
  modalStyles: {
    height: "auto",
    width: "90%",
    flexDirection: "column",
    justifyContent: "flex-start",
    alignItems: "center",
    backgroundColor: "#fff",
    borderColor: "#777",
    borderWidth: 1,
    
    marginLeft: 20,
   
  },
  fieldsContainer: {
    width: "100%",
  },
  fieldItem: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "space-between",
    paddingLeft: 12,
    borderBottomWidth: 1,        
    borderBottomColor: "#ebebeb",
  },
  fieldText: {
    color: "#444",
  },
  radioButtonContainer: {
    flexDirection: "row",   
    justifyContent: "flex-start",
    alignItems: "center",
  
  },
  singleRadioButtonContainer: {
    flexDirection: "row",
    justifyContent: "center",
   
    alignItems: "center",
    marginRight: 10,
    
  }, 
  buttonContainer: {
    flexDirection: "row",
    justifyContent: "center",
    alignItems: "center",
 
  },
  button: {
    width: "100%",
    marginHorizontal: 8,
  },
});

App.js

import * as React from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import Constants from 'expo-constants';

// You can import from local files
import Sortby from './components/Sortby';

// or any pure javascript modules available in npm
import { Card } from 'react-native-paper';

export default class App extends React.Component {

   state = {    
    showSortby: false,
  };

  startSortByHandler = () => {
    this.setState({
      showSortby: true,
    });
  };

  endSortByHandler = () => {    
    this.setState({
      showSortby: false,
    });
  };

  getSortValues = () => {
    this.endSortByHandler()  
  }

  getShowInGridViewList = () => {   
    const gridFieldArray = [
      {"text":"Organization","key":"0.7204364607892255"},
      {"text":"Document No","key":"0.11948720939854396"},
      {"text":"Warehouse","key":"0.5981352662697218"},
      {"text":"Business Partner","key":"0.3617080891091381"},
      {"text":"Partner Address","key":"0.9242697027340077"},
      {"text":"Movement Date","key":"0.19100558269330914"}] 
    return gridFieldArray;
  };

  render() {
  return (
    <View style={styles.container}>     
      <Card>
        <Sortby
          visible={this.state.showSortby}
          onCancel={this.endSortByHandler}
          showInGridViewList={this.getShowInGridViewList}     
          onOK={this.getSortValues}     
        ></Sortby>
        <Button title={'Open Modal'} onPress={this.startSortByHandler}></Button>
      </Card>
    </View>
  );
}
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    paddingTop: Constants.statusBarHeight,
    backgroundColor: '#ecf0f1',
    padding: 8,
  } 
});
2 Answers

There is a pattern called Lifting Up State where sharing the state is accomplished by moving it up to the closest common ancestor of the components that need it.

A state is created in the parent component and the setter for that state is passed to the child component.

That way, whenever the state is setted in the child component, you can manage it in the parent component too.

Create state in parent component and pass it to your child component

Related