I am trying to use react-native-sidemenu https://github.com/react-native-community/react-native-side-menu
My code looks like this.
There is no error and even output is overlapping to each other
var list = [{name: "komaldeep", subtitle: "dssdfds", avatar_url:"sadasdsa" }];
export default class First extends Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
};
this.toggleSideMenu = this.toggleSideMenu.bind(this);
}
toggleSideMenu () {
this.setState({
isOpen: !this.state.isOpen
})
}
render() {
//menu list `enter code here`
const MenuComponent = (
<View style={{flex: 1, backgroundColor: '#ededed', paddingTop: 200}}>
<List containerStyle={{marginBottom: 20}}>
{
list.map((l, i) => (
<ListItem
roundAvatar
onPress={() => console.log('Pressed')}
avatar={l.avatar_url}
key={i}
title={l.name}
subtitle={l.subtitle}
/>
))
}
</List>
</View>
)
return (
<SideMenu
isOpen={this.state.isOpen}
menu={MenuComponent} >
//Menu Component just contain some random text
<Menu toggleSideMenu={this.toggleSideMenu.bind(this)}/>
</SideMenu>
);
}
}
Can you just guide me.. what i am doing wrong..
OutPut looks like this
enter image description here
The reason that the items in your menu shows up on the right of the screen, seemingly outside of the menu, is that your MenuComponent takes up the entire screen. Set the prop openMenuOffset={number} to SideMenu and use the same number to set width: number in the style of your MenuComponent.
Related
How The App works!
I have an app that shows a list of names and after that shows the meaning of the Name depends on some preference the user choose it from a dropDowns.
So in total there is a Main of 3 Screens!
First: is the UI screen that asks user to choose data,
Second: is the screen that holds a list contains names, I list them using a FlatList (BTW the data retrives from a SqLite -not important-)
Third: is the Screen that shows the name's meaning,
I am navigating from the "Main-Screen" to the "NameList-Screen" then To the "NameMeaning-Screen",
The navigation to the "NameMeaning-Screen" done by pressing on an item from the List.
Till here the app working nicely!
I decided to add a new feature to the app and that to show all the names i have in my DB and show it in a screen that have two Tabs, The first tab shows male's names and the second tab shows the female's names.
I did that step too.
But What am facing now is!
I want to navigate from that tabs when pressing on an item from the flatList, and navigate to the "Third Screen" I mentioned above the name's meaning!
But it gave error that, there is no such screen called "NameMeaing" and then it says " Name screen Its not handled by any navigator", So as much as i understand, when am in the Tabs the program have no access to the stack Navigator and cuz of this it gives that error.
As much as i was able to find on Web, There is examples of navigating from tabs to another stack screens, but in the all the examples, the tabs were the main screen in the applicaiton, but in my case i reach the tabs after pressing a certain button and navigate to another stacked screen.
As a soluation for the problem i thought about creating a secondry stack navigator inside my Tabs.js file that contains the tabs but i couldnt, then i thought i should create a Tab navigator in my App.js adding it to my stack navigator that already exists there and compine them in a navigator container. Maybe this is the soluation but i couldnt complete the code and connect the dots. Any help please?!
This is a video of the app while working (The scenario)
https://youtu.be/dBLNF5zMCt0
This is the Error it shows:
Error when i try to navigate from a tab screen to another different screen
This is App.js file
import 'react-native-gesture-handler';
import React, {Component} from 'react';
import {createStackNavigator} from 'react-navigation-stack';
import {createAppContainer} from 'react-navigation';
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
import MainScreen from './MainScreen';
import NamesList from './NamesList';
import NameMeaning from './NameMeaning';
import NameListWithTabsAgirlAboy from './NameListWithTabsAgirlAboy';
const App = createStackNavigator(
{
MainScreen: {
screen: MainScreen,
navigationOptions: {
header: null,
},
},
NamesList: {
screen: NamesList,
navigationOptions: {
header: null,
},
},
NameListWithTabsAgirlAboy: {
screen: NameListWithTabsAgirlAboy,
navigationOptions: {
header: null,
},
},
NameMeaning: {
screen: NameMeaning,
navigationOptions: {
header: null,
},
},
},
{
initialRouteName: 'MainScreen',
}
);
export default createAppContainer(App);
This is NameMeaninng.js file
class NameMeaning extends Component {
constructor(props) {
super(props);
}
render() {
const {navigation} = this.props;
return(
<SafeAreaView style= {styles.container}>
<Text style={styles.title}>معنى اسم {JSON.stringify(navigation.getParam('nameTitle', 'NO-ID'))}</Text>
<ScrollView style={styles.scrollView}>
<Text style={styles.text}>
{JSON.stringify(navigation.getParam('explaination', 'NO-ID'))}
</Text>
</ScrollView>
</SafeAreaView>
);
}
}
this is parts of Tabs.js file
This file have three classes in totall. BoysScreen, GirlsScreen and Tabs classes..
class BoysScreen extends React.Component {
constructor(props) {
super(props);
const {navigation} = this.props;
}
render() {
let FlatListNames = [];
FlatListNames = boysNames();
const {navigation} = this.props;
function Item({ title }, {navigation}) {
return (
<View style = {StyleSheet.item}>
<Text styel = {styles.title}> {title} </Text>
<Text style ={StyleSheet.explain}>اضغط للشرح</Text>
</View>
)
}
function boysNames() {
var boysNamesList = [];
db.transaction(tx => {
// boys names
tx.executeSql('SELECT ID, Name, Explanation FROM Names WHERE NameSex=?', ["لـ طفلي"], (tx, results) => {
for (let i = 0; i < results.rows.length; ++i) {
boysNamesList.push(results.rows.item(i));
}
});
}); // DB transaction
return boysNamesList;
};
return(
<View style= {styles.container}>
<FlatList
data={FlatListNames}
keyExtractor={(item, index) => index.toString()}
renderItem={({ item }) =>
<TouchableOpacity
onPress = {() => {this.props.navigation.navigate('NameMeaning',{
nameTitle : item.Name,
nameId : item.ID,
explaination : item.Explanation,
});
}}
>
<Item title = {item.Name}/>
</TouchableOpacity>
}
/>
</View>
);
}
}// ends of BoysScreen Class
class Tabs extends React.Component {
constructor(props){
super(props);
}
render() {
const Tab = createMaterialTopTabNavigator();
// I have tried to create a stack here but it gave errors and couldnt solve it
//cont Stack = createStackNavigator();
return(
<NavigationContainer>
<Tab.Navigator>
<Tab.Screen name ="FemaleNames" component = {GirlsScreen} /> //GirlsScreen is a class
<Tab.Screen name = "MaleNames" component = {BoysScreen} /> // BoysScreen is a class
</Tab.Navigator>
// I have tried to import NameMeanig class and navigate to it like this, but it gaves errors too.
//<Stack.Screen name="Home" component={NameMeaning} />
</NavigationContainer>
);
}
Thanks in advance, any help of how i can build this algorithm is appricated really..
It was a problem with version compatibility, i was using React navigation V4 and V5 alltogether, After Searching more i have solved it in this way, Changing App.js and compine all the stacks and tabs navigators in App.js
Credit to this guy : https://www.youtube.com/watch?v=nQVCkqvU1uE
import 'react-native-gesture-handler';
import React, {Component} from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createMaterialTopTabNavigator } from '#react-navigation/material-top-tabs';
import MainScreen from './App/components/Home/MainScreen';
import NamesList from './App/components/NameList/NamesList';
import NameMeaning from './App/components/NameMeaning/NameMeaning';
import GirlNamesScreen from './App/components/NameList/GirlsNamesTab';
import BoysNamesScreen from './App/components/NameList/BoysNamesTab';
const MainStack = createStackNavigator();
const MainStackScreen = () => (
<MainStack.Navigator>
<MainStack.Screen
name="MainScreen"
component={MainScreen}
options={{ title: "Main Screen title" }}
/>
<MainStack.Screen
name="NamesList"
component={NamesList}
options={{ title: "NamesList Screen title" }}
/>
<MainStack.Screen
name="NameMeaning"
component={NameMeaning}
options={{ title: "NameMeaning Screen title" }}
/>
<MainStack.Screen
name="TabsScreen"
component={TabsScreen}
options={{ title: "TabsScreen Screen title" }}
/>
</MainStack.Navigator>
);
const Tabs = createMaterialTopTabNavigator();
const GirlNamesStack = createStackNavigator();
const BoysNamesStack = createStackNavigator();
const GirlNamesStackScreen = () => (
<GirlNamesStack.Navigator>
<GirlNamesStack.Screen name="GirlsNames" component={GirlNamesScreen} />
</GirlNamesStack.Navigator>
);
const BoysNamesStackScreen = () => (
<BoysNamesStack.Navigator>
<BoysNamesStack.Screen name="BoysNames" component={BoysNamesScreen} />
</BoysNamesStack.Navigator>
);
const TabsScreen = () => (
<Tabs.Navigator>
<Tabs.Screen name="BoysNames" component={BoysNamesStackScreen} />
<Tabs.Screen name="GirlsNames" component={GirlNamesStackScreen} />
</Tabs.Navigator>
);
const RootStack = createStackNavigator();
const RootStackScreen = () => (
<RootStack.Navigator headerMode="none">
<RootStack.Screen
name="Main"
component={MainStackScreen}
options={{
animationEnabled: false
}}
/>
</RootStack.Navigator>
);
export default () => {
return (
<NavigationContainer>
<RootStackScreen/>
</NavigationContainer>
);
};
I am new to react native and while going through a tutorial , I got stuck with scrolling of FlatList. On the tutorial with the same code I can see the list is scrolling. I am using Android emulator.
class LibraryList extends Component {
renderItem = ({ item }) => (
<ListItem library={item} />
);
render() {
console.log(this.props.libraries);
return (
<FlatList
data={this.props.libraries}
renderItem={this.renderItem}
keyExtractor={library => library.id.toString()}
/>
);
}
}
const mapStateToProps = state => {
return { libraries: state.libraries };
};
export default connect(mapStateToProps)(LibraryList);
Try by wrapping your FlatList with the empty View having flex is 1.
So your render method code will be like below code:
render() {
console.log(this.props.libraries);
return (
<View style={{flex:1}}>
<FlatList
data={this.props.libraries}
renderItem={this.renderItem}
keyExtractor={library => library.id.toString()}
/>
</View>
);
}
Hope this will help you.
Try this code block (example , change this self code)
renderFlatList() {
return (
<FlatList
data={this.props.database}
ListHeaderComponent={() => this.renderAddFeedScool()}
renderItem={({ item }) => this.renderItem(item)}
/>
);
}
render() {
return (
<View style={_styles.container}>
{this.props.database.length > 0 ? (
this.renderFlatList()
) : (
<Text>Loading</Text>
)}
</View>
);
}
Styles..
container: {
flex: 1,
},
Full code : https://github.com/VB10/Nativer/blob/master/src/view/tab/school/index.tsx
And look at https://facebook.github.io/react-native/docs/flatlist
and :) final solution use native-base list component i think exactly solution https://docs.nativebase.io/Components.html#list-def-headref
Good work.
I'm making a list view were I will view a list of some data from my database. But after running the program all I got is white background screen. Does anyone knows the solution?
screen shot
Here is my code
export default class Pasta extends Component {
constructor() {
super()
this.state = {
dataSource: []
}
}
renderItem = ({ item }) => {
return (
<View style = {{flex: 1, flexDirection: 'row'}}>
<View style = {{flex: 1, justifyContent: 'center'}}>
<Text>
{item.menu_desc}
</Text>
<Text>
{item.menu_price}
</Text>
</View>
</View>
)
}
componentDidMount() {
const url = 'http://192.***.***.***:9090/menu'
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.menu
})
})
}
render() {
return (
<View style = { styles.container }>
<FlatList
data = { this.state.dataSource }
renderItem = {this.renderItem}
/>
</View>
);
}
}
Add extraData prop to your FlatList to cause a re-render
keyExtractor = (item, index) => item.id; // note: id is the unique key for each item
render() {
return (
<FlatList
data = {this.state.dataSource}
renderItem = {this.renderItem}
extraData={this.state}
keyExtractor={this.keyExtractor}
/>
);
}
Also log and verify your data is present. I suggest referring to FlatList docs for more props like keyExtractor etc.
I am new to React Native so excuse the question if this is simple. I am trying to toggle icons in a ListView. How should I go about this? Your help is much appreciated.
Here's a piece of code i'm working with.
this.state = {
logo: 'star-o',
check: false
};
saveFavourite = (data) => {
this.state.check === false ? this.setState({logo:'star', check:true}) : this.setState({logo:'star-o', check:false})
}
<TouchableOpacity onPress={() => this.saveFavourite(data)}>
<Icon name={this.state.logo} size={30} />
</TouchableOpacity>
it din't change the icon.
First I can guess by your code that you are addressing this in the component holding the list view. This is wrong because you cant define a state to every "loveable" component, mainly because you cannot know how many are they beforehand. Instead, you should try to make this component dummy and receive if it is loved or not by props.
Then you should put a callback inside your component to execute code from your parent Component. Something like this:
class MyListComponent extends React.Component {
state = {
items: [
{ text: 'Some text', loved: false },
{ text: 'Some text2', loved: true },
],
}
toggleLoved() => {
// your logic here
}
render() {
return(
<FlatList
data={this.state.items}
renderItem={(item) => {
<MyLoveableComponent
loved={item.item.loved}
onLoved={ () => this.toggleLoved() }
}/>
);
}
}
const MyLoveableComponent = ({ loved, onLoved, logo }) => {
return(
<TouchableOpacity
onPress={() => {
setFavourite();
onLoved();
}>
<Icon name={logo} size={30} />
</TouchableOpacity>);
}
}
Check the component-container design pattern and remind that components should be as dummy as possible.
I have my side menu via DrawerNavigator. I know that to customize the drawer, it's in "contentComponents" props.
I want for example, put a button who open a modal like : Share (to share the app on other social media)
But for now, all my button are route. So if I click on it, it's redirect to the page (normal). I just want to add a button who react and not redirect.
I don't know how to custom that in the Component dynamically. I think about hardcoded each button (some for redirect, some for display simple modal).
Here is my code :
index.android.js
const DrawerContent = (props) => (
<ScrollView>
<View style={styles.container}>
<Text style={styles.logo}>TechDico</Text>
<Text style={{ paddingLeft: 10, paddingRight: 10, fontSize: 13, textAlign: 'center', color: '#f4f4f4' }}>Des millions de traductions classées par domaine d'activité</Text>
</View>
<DrawerItems style={{ marginTop: 30 }} {...props} />
</ScrollView>
)
const appNavigator = DrawerNavigator({
Redirection1: {
screen: Index,
navigationOptions: {
drawerLabel: 'Redirection1',
drawerIcon: ({ tintColor }) => (<Icon name="home" size={20} color={tintColor} />),
}
},
DisplayModal: {
screen: Index,
navigationOptions: {
drawerLabel: 'DisplayModal',
drawerIcon: ({ tintColor }) => (<Icon name="home" size={20} color={tintColor} />),
}
},
Redirection2: {
screen: Index,
navigationOptions: {
drawerLabel: 'Redirection2',
drawerIcon: ({ tintColor }) => (<Icon name="home" size={20} color={tintColor} />),
}
}, }, {
// define customComponent here
contentComponent: DrawerContent,
contentOptions: {
inactiveTintColor: '#000000',
activeTintColor: '#1eacff',
showIcon: true,
}
});
Index class
export default class Index extends Component {
renderRoot = () => {
const { navigation } = this.props;
console.log("My Navigation ", navigation);
switch (navigation.state.key) {
case 'Redirection1':
return (
<App navigation={navigation} />
);
case 'DisplayModal':
// TODO I don't want to return so I can remove to cancel the redirection, but now, how can I display a modal without redirect.
return (
<DisplayModal navigation={navigation} />
);
case 'Redirection2':
return (
<Redirection2 navigation={navigation} />
);
default:
return (
<Test navigation={navigation} />
);
}
}
I'm using 'react-navigation'.
I'm looking at the same task as well. I think having multiple routes pointing to the same screen type may cause eventually a mess with state management, as each screen instance is different.
Looking at the source code in DrawerSidebar/DrawerNavigatorItems it seems all items in the sidebar list are those found in drawer's route config (unless we rewrite completely DrawerNavigatorItems). So maybe we may have a fake screen for some route and in componentWillMount implement required action and then navigate to the default route.
Here is a sample code:
let drawer = DrawerNavigator({
Main: {
screen: MainScreen,
},
About: {
screen: AboutScreen,
},
ContactUs: {
screen: ContactUsFakeScreen,
},
});
const mailUrl = "mailto:test#test.com";
class ContactUsFakeScreen extends React.Component {
componentWillMount() {
let self = this;
Linking.canOpenURL(mailUrl)
.then(self.openEmail)
.catch(err => self.openEmail(false));
}
openEmail(supported) {
if (supported) {
Linking.openURL(mailUrl).catch(err => {});
}
let { navigation } = this.props;
navigation.navigate('Main');
}
render() {
return null;
}
}
Here Main/MainScreen and About/AboutScreen are regular routes and screens, while ContactUs/ContactUsFakeScreen only pretend to be a route and a screen. Clicking on ContactUs will trigger componentWillMount which deals with email screen and then eventually navigates to the MainScreen (Main route).
Another approach could be to hijack getStateForAction from drawer router and put some extra routing logic there replacing destination route on the fly. Something along these lines:
const defaultDrawerGetStateForAction = drawer.router.getStateForAction;
drawer.router.getStateForAction = (action, state) => {
let newState = defaultDrawerGetStateForAction(action, state);
if (action.type === 'Navigation/NAVIGATE' && action.routeName === 'ContactUs') {
// extra logic here ...
newState.routes.forEach(r => {
if (r.key === 'DrawerClose') {
// switching route from ContactUs to Main.
r.index = 0;
}
});
}
return newState;
}
And if an item in the drawer list is not even actionable (like copyright), then fake screen will look even simpler (note styling via navigationOptions):
let drawer = DrawerNavigator({
...
Copyright: {
screen: Copyright,
},
});
class Copyright extends React.Component {
static navigationOptions = {
drawerLabel: ({ tintColor, focused }) =>
(<Text style={{color: '#999'}}>Copyright 2017</Text>)
)
};
componentWillMount() {
let { navigation } = this.props;
navigation.navigate('Main');
}
render() {
return null;
}
}