0

I have following problem:

I intend to fetch data via web API and on its basis, React Native will render it using FlatList. It will use a child component, in this case (Checkbox). So, there will be multiple checboxes.

How can I create and update state of these checboxes when I don't know their count and then pass their state to child component?

const data = [{
   id:0,
   product:"A"
   price:30
},
{
   id:1,
   product:"B"
   price:20
},
{
   id:1,
   product:"C"
   price:10
}]

enter image description here

(I am scratching my head)

5
  • 1
    Please post the code instead of the problem statement. What is the form of data that you are getting from API? If you don't have code then post UI pics and explain further so people can give you a specific answer without going back and forth after posting answers. Commented Dec 4, 2020 at 21:48
  • Code can help us help you better than the problem you are facing. Commented Dec 4, 2020 at 21:54
  • @KetanRamteke - I am trying to accomplish this so I don't the code. Though, I have added the UI design and data feed. The issue is that the feed can change, from 3 products to 5 and more... if they were static, it was very easy to save the state. But in this case, how can I accomplish this? Commented Dec 4, 2020 at 22:06
  • Nice, so when you click on checkboxes what are the app behaviors that you are intending to achieve? Should selected items be passed to another screen after navigating or update the state with the mutated list with checked/unchecked information? Commented Dec 4, 2020 at 22:11
  • when pressed/selected, the respective product will show check mark (by passing state to Child component). There is a 'buy' button at the end which will open the modal and will show the selected products and total price, user will click 'confirm' to complete the purchase and the data of selected products with customer information will be sent to server. Commented Dec 4, 2020 at 22:18

2 Answers 2

1

Output:

enter image description here

Here is the working example of an app showing data selection and flow of it to the next screen, implement data fetching, and server-side execution accordingly.

import React, { useState, useEffect } from 'react';
import {
  Text,
  View,
  StyleSheet,
  FlatList,
  CheckBox,
  Button,
  Modal,
} from 'react-native';
import Constants from 'expo-constants';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';

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

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

const data = [
  {
    id: 0,
    product: 'A',
    price: 30,
    selected: false,
  },
  {
    id: 2,
    product: 'B',
    price: 20,
    selected: false,
  },
  {
    id: 3,
    product: 'C',
    price: 10,
    selected: false,
  },
];

const Stack = createStackNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator initialRouteName="Home">
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Payment" component={PaymentScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}

function PaymentScreen({ navigation, route }) {
  const { selected } = route.params;
  return (
    <FlatList
      data={selected}
      renderItem={({ item }) => (
        <Card style={{ margin: 5 }}>
          <View style={styles.card}>
            <View
              style={{
                flexDirection: 'row',
                width: 50,
                justifyContent: 'space-between',
              }}>
              <Text>{item.product}</Text>
            </View>
            <Text>{item.price} USD</Text>
          </View>
        </Card>
      )}
    />
  );
}

function HomeScreen({ navigation }) {
  const [products, setProducts] = useState(data);
  const [showModal, setShowModal] = useState(false);
  const [selected, setSelected] = useState([]);

  const handleChange = (id) => {
    let temp = products.map((product) => {
      if (id === product.id) {
        return { ...product, selected: !product.selected };
      }
      return product;
    });
    setProducts(temp);
  };

  const getSelected = () => {
    let temp = products.filter((product) => product.selected);
    setSelected(products.filter((product) => product.selected));
    console.log(temp);
  };

  useEffect(() => {
    getSelected();
  }, [showModal]);

  return (
    <View style={styles.container}>
      <Modal animationType="slide" transparent={true} visible={showModal}>
        <View style={styles.modalView}>
          <FlatList
            data={selected}
            renderItem={({ item }) => (
              <Card style={{ margin: 5 }}>
                <View style={styles.card}>
                  <View
                    style={{
                      flexDirection: 'row',
                      width: 50,
                      justifyContent: 'space-between',
                    }}>
                    <Text>{item.product}</Text>
                  </View>
                  <Text>{item.price} USD</Text>
                </View>
              </Card>
            )}
          />
          <Text>
            Total :{' '}
            {selected.reduce((acc, curr) => acc + curr.price, 0).toString()}
          </Text>
          <Button
            title={'BUY'}
            onPress={
              selected
                ? () => {
                    setShowModal(false);
                    navigation.navigate('Payment', { selected: selected });
                  }
                : setShowModal(false)
            }
          />
        </View>
      </Modal>
      <FlatList
        data={products}
        renderItem={({ item }) => (
          <Card style={{ margin: 5 }}>
            <View style={styles.card}>
              <View
                style={{
                  flexDirection: 'row',
                  width: 50,
                  justifyContent: 'space-between',
                }}>
                <CheckBox
                  value={item.selected}
                  onChange={() => {
                    handleChange(item.id);
                  }}
                />
                <Text>{item.product}</Text>
              </View>
              <Text>{item.price} USD</Text>
            </View>
          </Card>
        )}
      />
      <Button
        title={'ADD TO CART'}
        onPress={() => {
          setShowModal(true);
          console.log(showModal);
        }}
      />
    </View>
  );
}

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

  card: {
    padding: 10,
    margin: 5,
    flexDirection: 'row',
    justifyContent: 'space-between',
  },
  modalView: {
    margin: 20,
    backgroundColor: 'white',
    borderRadius: 20,
    padding: 5,
    justifyContent: 'space-between',
    alignItems: 'center',
    elevation: 5,
  },
});

You can play with the working code here: Expo Snack

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you so much for the detailed reply. I find it very helpful. I'll go through it and will update you.
Of course, it will not work as-is, you will have to make a few modifications here and there according to your project. Anyhow, I hope this answer helps you and meanwhile, Happy Coding.
Your code helped me in understanding the concept of fetching and rendering long lists. I just have a question, is there any way to do this without adding (selected:false) property to each object in the data array? What if I have nested properties for which I need to keep states?
you can do it, use the id key of the products list, and when the checkbox is clicked, add that id to a new state and use that state to find out which checkbox is checked or not, and when unchecked, just remove that id from the state holding the checked array id.
Can you please also view this question and share your views: stackoverflow.com/questions/65160091/…
|
0

This is simple logic code and you would have to implement it in your way of needed

checkBoxChanged = (index) => {
       const newData = [...this.state.data];
       const newData[index].checked = !newData[index].checked;
       this.setState({data: newData});       
}

{this.state.data((item, i) => {
       return (
         <View>
          .......                                   
          <CheckBox
            ......
            checked={item.checked || false}
             onValueChange={() => this.checkBoxChanged(i)}
          />
          .......  
        </View>
})}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.