Hi I want simple a button select and deselect when I have lots of buttons in one page like toggle select but no other button will effect.
My code like below:
constructor(props) {
super(props);
this.state = {
activeState: [false, false, false]
};
this.buttonPressed = this.buttonPressed.bind(this);
}
buttonPressed(index) {
// I want to update array value true and false.
}
<TouchableOpacity
style={this.state.activeClasses[0] ? styles.rateButton :
styles.rateButtonActive}
onPress={() => this.addActiveClass(0)}>
</TouchableOpacity>
<TouchableOpacity
style={this.state.activeClasses[1] ? styles.rateButton :
styles.rateButtonActive}
onPress={() => this.addActiveClass(1)}>
</TouchableOpacity>
You can suggest me a different process or method by which I can make this.
I don't know if this is exactly what you want, but i'll give it a try:
buttonPressed(index) {
const tmpState = this.state.activeState.map((val, tmpIndex) => {
if (tmpIndex === index) {
return !val;
}
return val;
});
this.setState({ activeState: tmpState });
}
Related
I want to check if data exist, If data exist then to show red button and if there is no data then it will show blue button. I tried to do that but its not working . For example Instagram go to DM's button if there are any DM , button change to different color with number of DM's unread and if there is no Dm's then it is simple button.
static navigationOptions = ({ navigation }) => {
const { params = {} } = navigation.state;
const { notifications } = this.props.notification;
return {
headerRight: (
<View>
{
(notifications.length > 0) ? (
<TouchableOpacity onPress={() => params.handleSave()}>
<Badge>
<Text>{notifications.length}</Text>
</Badge>
</TouchableOpacity>
) : (
<TouchableOpacity onPress={() => params.handleSave()}>
<Ionicons
name="ios-notifications-outline"
style={{ paddingRight: 15 }}
size={24}
color="white"
/>
</TouchableOpacity>
)
}
</View>
)
};
}
create two different styles and condition
style={[navigation.state.yourstate ? styles.selectedButtonStyle : styles.normalButtonStyle]}
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;
}
}
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.
I know how to add and remove a single component by changing the state. But this way wont work if you have multiple components to remove. For instance lets say I have 3 Views. How can I remove them when I click on them.
Example code:
class Example extends Component {
render(){
return (
<View>
<View>
<TouchAbleOpacity onPress={() => this.removeView()}>
<Text>Remove View 1</Text>
</TouchAbleOpacity>
</View>
<View>
<TouchAbleOpacity onPress={() => this.removeView()}>
<Text>Remove View 2</Text>
</TouchAbleOpacity>
</View>
<View>
<TouchAbleOpacity onPress={() => this.removeView()}>
<Text>Remove View 3</Text>
</TouchAbleOpacity>
</View>
</View>
)
}
removeView(){
}
}
Another example will be when I have a ListView with buttons inside. These are buttons to invite a user. When I click on the button I want to hide the button for that specific row in the ListView.
Any suggestions?
Thanks to Giorgos I found a solution for my own question. I created a separate component with a hide function inside the component. Now I can just add this component anywhere in a view or in a listView and when I click on it it will hide. Remember this only hides the component and does not unmount it.
This is just an example so I created a button component.
My Button Component:
class ButtonComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
hide:false
}
}
render() {
return (
<View style={styles.container}>
{this.renderButtonComponent()}
</View>
);
}
renderButtonComponent(){
if(!this.state.hide){
return (
<TouchableOpacity onPress={this.hide.bind(this)}>
<Text>Button</Text>
</TouchableOpacity>
);
}
}
hide(){
this.setState({
hide:true
});
}
}
In my View I just render my Component:
render() {
return (
<View style={styles.container}>
<ButtonComponent/>
<ButtonComponent/>
<ButtonComponent/>
</View>
);
}
You have to use your component's state. Whenever you call setState the component's render() function is triggered again. There based on what the current state is, you can decide what to show and what not. For example:
class Example extends Component {
constructor(props){
// initialize state
this.state = {
isView1Visible: true,
isView2Visible: true,
isView2Visible: true
}
}
render(){
return (
<View>
{ this.renderView1() }
{ this.renderView2() }
{ this.renderView3() }
</View>
)
}
renderView1(){
if(this.state.isView1Visible){
return (
<View>
<TouchAbleOpacity onPress={() => this.setState( {isView1Visible: false} )}>
<Text>Remove View 1</Text>
</TouchAbleOpacity>
</View>
)
}
renderView2(){
if(this.state.isView2Visible){
return (
...
)
}
renderView3(){
if(this.state.isView3Visible){
return (
...
)
}
}
In the above example, you render your view based on the current state. When the button is clicked, you update the state by calling setState() which, like I mentioned before, will trigger another call to render().
With the ListView the approach is the same but the implementation slightly different. What you need to do there is to save your list of items in the state of your component and whenever you want to add/remove an item, you update the list accordingly and then update the state using setState. For example, something similar to this:
constructor(props) {
super(props);
var list = [ ... ]
const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });
this.state = {
dataSource: ds,
items: ds.cloneWithRows(list)
};
}
render() {
return (
<View>
<ListView
dataSource={this.state.items}
renderRow={(rowData) => this.renderRow(rowData) /> } />
</View>
)
}
renderRow(rowData) {
<View>
<TouchAbleOpacity onPress={() => this.updateList()}>
<Text>Remove View 1</Text>
</TouchAbleOpacity>
</View>
}
updateList() {
// do some changes to your list and update the state.
var newItems = ...
this.setState({
items: newItems
})
}
Hope this helps.