0xgareth
0xgareth

Reputation: 621

React Native: Conditional Render not working as it should

I have a conditional statement that determines which JSX should be rendered on screen. It looks at an array held in the state, and, if empty, renders an image and some text. However, if populated, the data is rendered using Flat List.

When the conditional statement equates to false (the array is empty) the image and text are rendered very briefly (for around half a second).

How can I alter it so it does not appear at all? As the logic would suggest.

My code is below:

render() {
if (this.state.array === undefined || this.state.array.length === 0) {
  return (
    <View>
      <View>
        <Text> Tap the (+) button to add an item.</Text>
        <Image source={require('../images/image.png')} />
      </View>
    </View>
    );
}

//If array data
return (
    <View>
      <FlatList
          data={this.state.array}
          renderItem={({ item }) => <TrackedItem {...item} />}
          keyExtractor={(item, index) => index.toString()}
      />
    </View>
   );
 }

Upvotes: 0

Views: 1363

Answers (2)

soutot
soutot

Reputation: 3671

Maybe your issue is related to your condition. You are checking for this.state.array and then for this.state.foods.

I rewrote some pieces of your code that may work as expected

const { foods } = this.state;
render() {
  return (
    <View>
     {!foods || foods.length === 0 ?
      <View>
        <Text> Tap the (+) button to add an item.</Text>
        <Image source={require('../images/image.png')} />
      </View>
      :
      <FlatList
          data={foods}
          renderItem={({ item }) => <TrackedItem {...item} />}
          keyExtractor={(item, index) => index.toString()}
      />
     }
    </View>
    );
 }

Just replace foods for array according to the correct prop declared in your state

This code will display the text Tap the (+)... when your array is empty.

So you don't want to display this text after all? If so, you can just change the condition to only render <FlatList> if your array exists and if it's length is > 0, something like:

return (
    <View>
     {(foods && foods.length > 0) &&
      <FlatList
          data={foods}
          renderItem={({ item }) => <TrackedItem {...item} />}
          keyExtractor={(item, index) => index.toString()}
      />
     }
    </View>
  );

If you want only to not display in the first render, then you might need a loading handler. Something like this:

state = {
  foods: [],
  loading: true,
}

async componentDidMount() {
  const yourArray = await getArrayValues(); // here you replace for whatever you use to fetch your data. Remember to use async/await, so you avoid triggering setState before the fetch is completed
  this.setState({
    foods: yourArray,
    loading: false,
  })
}

render() {
  const { foods, loading } = this.state;
  if (loading) return <ActivityIndicator />

  return (
    <View>
     {!foods || foods.length === 0 ?
      <View>
        <Text> Tap the (+) button to add an item.</Text>
        <Image source={require('../images/image.png')} />
      </View>
      :
      <FlatList
          data={foods}
          renderItem={({ item }) => <TrackedItem {...item} />}
          keyExtractor={(item, index) => index.toString()}
      />
     }
    </View>
    );
 }

Hope it helps

Upvotes: 1

0xgareth
0xgareth

Reputation: 621

As per MattyK14's recommendation, I included a spinner (or loading screen) that renders until the data is retrieved. This prevented the 'no data' screen from rendering very briefly before the list is returned.

This is included above the if statement:

  if (this.state.loading) {
  return <Spinner />;
}

Upvotes: 0

Related Questions