Mandalina
Mandalina

Reputation: 446

React-Native Conditional Rendering with JSON data

I have data that looks like this:

// items.json    
[
      {
        "key": 1,
        "category": "Fruits",
        "colors": [
          {
            "color": "red",
            "favourite": "apple"
          },
          {
            "color": "orange",
            "favourite": "orange"
          }
        ]
      }, 
      {
        "key": 2,
        "category": "Vegetables",
        "colors": [
          {
            "color": "orange",
            "favourite": "carrot"
          },
          {
            "color": "green",
            "favourite": "celery"
          }
        ]
      }
    ]

But it can have an unlimited amount of objects in each array. What I want to do is initially display the categories, which I have done like this:

import Items from './items.json';

// and then I use it in the render method

    render() {
        var items= items;
    return (
         {items.map(item =>
             <TouchableOpacity
                 key={item.key}>
                <Text>
                  {item.category}
                </Text>
             </TouchableOpacity>
          )}
    )
}

Now when a category is pressed I want to hide the categories and display the colors. And then when the color is pressed I want to hide the colors and display the favourite.

I have tried doing this with if else statements, but it that won't work if the data is replaced, and as I mentioned this json object can be quite large. Please help!

Upvotes: 0

Views: 1074

Answers (2)

Junius L
Junius L

Reputation: 16122

Declare two arrays in your state, one for storing the original data and one for storing the filtered data based on which item was pressed.

state = {
  items: items, // original data
  data: items, // will filter data and display using .map()
  categoryIndex: 0, // index of the selected category
};

Add onPress to your TouchableOpacity and pass the type of the item that was pressed.

{this.state.data.map((item, index) => (
  <TouchableOpacity
    onPress={() =>
      this.onItemPress(
        item.category ? 'category' : item.color ? 'color' : 'favourite',
        index
      )
    }
    key={item.key}>
    <Text>{item.category || item.color || item.favourite}</Text>
  </TouchableOpacity>
))}

onItemPress, based on item that was pressed update state.data

onItemPress = (type, index) => {
  if (type === 'category') {
    this.setState({
      data: this.state.items[index].colors,
      categoryIndex: index,
    });
  }

  if (type === 'color') {
    this.setState({
      data: [
        {
          favourite: this.state.items[this.state.categoryIndex].colors[index]
            .favourite,
        },
      ],
    });
  }

  if (type === 'favourite') {
    this.setState({
      data: this.state.items,
      categoryIndex: 0,
    });
  }
};

DEMO

Upvotes: 1

Alvin Abia
Alvin Abia

Reputation: 1266

You need to:

  • track in your component state what the selected item or color index is so your render function knows when to rerender and what to render.
  • handle when an item is pressed by adding the onPress prop to your TouchableOpacity and updating the component state as mentioned above
    state = {
        selectedItemIndex: null,
        selectedColorIndex: null,
    };

    render {
        if (this.state.selectedColorIndex) {
           // return some jsx using this data below:
           // items[this.state.selectedItemIndex].colors[this.state.selectedColorIndex].favourite
        }        

        if (this.state.selectedItemIndex) {
            return (
                {items[this.state.selectedItemIndex].colors.map(color, i) => (
                    {/* return jsx here for colors */}
                )}
            );
        }

        return (
            {items.map((item, i) => (
                 <TouchableOpacity
                     key={item.key} 
                     onPress={() => this.setState({ selectedItemIndex: i })}>
                     <Text>
                         {item.category}
                     </Text>
                 </TouchableOpacity>
          ))}
        )
    }

Upvotes: 1

Related Questions