How to Create 3X3 Grid Menu in React Native Without 3Rd Party Lib

How to make this grid with logo header at the top?

Get rid of that grid component. You don't need it for such a simple thing. It's complicating things, and as it's not a regular/common component we don't know how it's affecting things.

This looks quite simple:

<View>
<View style={{}}>
<Image />
</View>

<View style={{flexDirection:'row'}}>
<View>
<Text>row 1, col 1</Text>
</View>
<View>
<Text>row 1, col2Text>
</View>
</View>

<View style={{flexDirection:'row'}}>
<View>
<Text>row 2, col 1</Text>
</View>
<View>
<Text>row 2, col2Text>
</View>
</View>

<View style={{}}>
<Button title="Login" />
</View>

</View>

Here's another similar question - How to create 3x3 grid menu in react native without 3rd party lib?

React Native Table with Row Selection

Thanks to a friend, I found 3 issues in the code that were causing the problem:

  1. When checking to see if the array contains the object, I first need to check that the array is an array and contains items. New check (wrapped in a function for reuse):

    checkIfChecked(id, selectedItems)
    {
    return selectedItems?.length && selectedItems.includes(id);
    }

  2. The state update was modifying the state without copying. New state update function:

    setSelection(id) {
    const { selectedItems } = this.state;

     if (this.checkIfChecked(id,selectedItems))
    {
    this.setState({selectedItems: selectedItems.filter(i => i != id)});
    }
    else
    {
    let selectedItemsCopy = [...selectedItems]
    selectedItemsCopy.push(id)
    this.setState({selectedItems : selectedItemsCopy});
    }

    }

  3. The onValueChange needed ()=> to prevent immediate triggering, which lead to a "Maximum Depth Reached" error. New version

    onValueChange={()=>this.setSelection(rowData[0])} />}

The full working code is here:

import React, { Component } from 'react';
import { StyleSheet, View } from 'react-native';
import CheckBox from '@react-native-community/checkbox';
import { Table, Row, TableWrapper, Cell } from 'react-native-table-component';
import moment from 'moment';

class FruitGrid extends Component {

constructor(props) {
super(props);
}
state = {
selectedItems : [],
data: []
};

refresh() {
let rows = [
[69,'David','Apples'],
[70,'Teddy','Oranges'],
[73,'John','Pears']
];
this.setState({data: rows});
}
componentDidMount() {
this.refresh();
}
setSelection(id) {
const { selectedItems } = this.state;

if (this.checkIfChecked(id,selectedItems))
{
this.setState({selectedItems: selectedItems.filter(i => i != id)});
}
else
{
let selectedItemsCopy = [...selectedItems]
selectedItemsCopy.push(id)
this.setState({selectedItems : selectedItemsCopy});
}
}

checkIfChecked(id, selectedItems)
{
return selectedItems?.length && selectedItems.includes(id);
}
render() {
const { selectedItems, data } = this.state;
let columns = ['',
'Person',
'Fruit'];

return (
<View style={{ flex: 1 }}>
<Table borderStyle={{borderWidth: 2, borderColor: '#c8e1ff'}}>
<Row data = {columns} />
{
data.map((rowData, index) =>
(
<TableWrapper key={index} style={styles.row}>
<Cell key={0} data = {<CheckBox value={this.checkIfChecked(rowData[0],selectedItems)} onValueChange={()=>this.setSelection(rowData[0])} />} />
<Cell key={1} data = {rowData[1]} textStyle={styles.text}/>
<Cell key={2} data = {rowData[2]} textStyle={styles.text}/>
</TableWrapper>
)
)
}
</Table>
</View>
);
}
}

export default FruitGrid;

const styles = StyleSheet.create({
btn: { width: 58, height: 18, backgroundColor: '#8bbaf2', borderRadius: 2 },
btnText: { textAlign: 'center', color: '#000000' },
text: { margin: 6 },
row: { flexDirection: 'row' },
});

In React Native how to navigate between screens?

As the above answer mentioned, you are not including Main Component to your navigation so, you can basically think like they are not connected each other whatsoever.

What I suggest you is having a PrimaryNavigator, you can think as Main component in your case.

const PrimaryNavigator = StackNavigator({    SignInStack: {        screen: SignInStackNavigator    },    SignUpStack: {        screen: SignUpStackNavigator    },    DrawerMainStack: {        screen: MenuDrawerStack    }},    {        headerMode: 'none'    });

I'm trying to load all the images as a scrollable menu but can't figure out how

While Edison makes a good point about good practices, I believe your problem is that you are just requiring the image twice. The output of the require() is what you need to pass to the Image component. You are doing require of a require.

<Image source={require(getImageForRestaurant(source))} />

Probably just changing to this should work:

<Image source={getImageForRestaurant(source)} />

100% width in React Native Flexbox

Simply add alignSelf: "stretch" to your item's stylesheet.

line1: {
backgroundColor: '#FDD7E4',
alignSelf: 'stretch',
textAlign: 'center',
},

How to align child views to left with even space in React-Native?

I took a different approach by using another view as a wrapper and doing the calculation of its width, this is easier to decide the column widths.
The only problem is that we should know the width of the item, wont be a problem in my case.
The code will be as below.

import React from 'react';
import { StyleSheet, View, ScrollView } from 'react-native';

export default class App extends React.Component {

constructor(props) {
super(props);
this.state = {
width: 110
};
}

render() {
//width of child is 110
const width = `${100 / parseInt(this.state.width / 110)}%`;
return (
<ScrollView>
<View style={styles.container} onLayout={this.onLayout.bind(this)}>
<View style={[styles.wrapper, { width: width }]}>
<View style={styles.box}></View>
</View>
<View style={[styles.wrapper, { width: width }]}>
<View style={styles.box}></View>
</View>
<View style={[styles.wrapper, { width: width }]}>
<View style={styles.box}></View>
</View>
<View style={[styles.wrapper, { width: width }]}>
<View style={styles.box}></View>
</View>
<View style={[styles.wrapper, { width: width }]}>
<View style={styles.box}></View>
</View>
</View>
</ScrollView>
);
}

onLayout(e) {
if (this.state.width !== e.nativeEvent.layout.width) {
this.setState({
width: e.nativeEvent.layout.width
})
}
}
}

const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'flex-start',
justifyContent: 'flex-start',
flexDirection: 'row',
flexWrap: 'wrap',
paddingTop: 40
},
box: {
width: 100,
height: 100,
backgroundColor: 'green',
},
wrapper: {
marginVertical: 10, alignItems: 'center'
}
});


Related Topics



Leave a reply



Submit