ctd25
ctd25

Reputation: 760

React Native - Cascade state updates from parent to child

I'm trying to cascade a state change from a parent component down to a child.

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

    this.listUpdater = new_list_updater();

    this.state = {
      schoollist: this.listUpdater.update_list(),
    }
  } 

  listUpdateCallback = () => {
    console.log("Callback triggered!");
    console.log(this.state.schoollist.slice(1,3));
    this.setState({schoollist: this.listUpdater.update_list()});
    console.log(this.state.schoollist.slice(1,3));
  }

  render() {
    return (
      <SafeAreaView style={styles.container}>
        <Header updateCallback={this.listUpdateCallback}/>
        <SchoolList school_list={this.state.schoollist}/>
      </SafeAreaView>      
    );
  }
}

listUpdater.update_list() is a method in a class that implements getISchools and ShuffleArray and stores the list of schools that are being shuffled. It returns the shuffled list of schools.

import { shuffleArray } from './Shuffle'
import { getISchools } from './iSchoolData'

class ListUpdater{
    constructor() {
        console.log("Initiating class!");
        this.currentSchoolList = [];
    }

    update_list() {
        console.log("Updating list!");
        if (this.currentSchoolList.length == 0){
            this.currentSchoolList = getISchools();        
        }
        else{
            shuffleArray(this.currentSchoolList);
        }
        return(this.currentSchoolList);
    }
}

export function new_list_updater(){
    return new ListUpdater();
}

As far as I can tell everything works. When I press a refresh button in the Header component, it triggers the updateCallback, which updates the list stored in the state variable (verified by logging to console and ComponentDidUpdate()

This is the Component not refreshing:

import React from 'react';
import { StyleSheet, Text, View, SafeAreaView, FlatList } from 'react-native';

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

    render() {
        return (
            <SafeAreaView style={styles.listArea}>
                <FlatList
                data = {this.props.school_list}
                renderItem = {({item}) =>
                    <View style={styles.row}>
                        <View style={styles.num_area}>
                            <Text style={styles.num_text}>{item.key}</Text>
                        </View>
                        <View style={styles.text_area}>
                            <Text style={styles.univ_text}>{item.univ}</Text>
                            <Text style={styles.school_text}>{item.school}</Text>
                        </View>
                    </View>
                }
                />
            </SafeAreaView>
        );
    }

    componentDidUpdate(){
        console.log("SchooList Updated!");
    }
}

The flow I'm expecting is:

  1. Parent passes updateCallback reference to Header (child)

  2. Refresh button in Header triggers updateCallback in Parent

  3. updateCallback in Parent updates state with setState

  4. Parent and relevant children that use state variable re-render, displaying new list

1-3 appear to be working, 4 is not!

Upvotes: 0

Views: 651

Answers (1)

Michael Wallace
Michael Wallace

Reputation: 432

Maybe your componenet is not re-rendering when you use setState for some reason. Try adding a warn in the render method to check this. I also noticed you are mutating the array this.currentSchoolList, winch is passade as reference for your state (all objects are passed as refence). Try replaceing this making a copy of the array beforing calling shuffleArray(this.currentSchoolList).

You can copy the array this way (this is ES6 sintax): newArray = [...oldArrray]; Or using other methods.

Upvotes: 1

Related Questions