React native toggle component without state - reactjs

I just want to toggle SearchButton and SearchIcon , I use following code
searchBarButton() {
Actions.refresh();
this.setState({ showSearchBar: !this.state.showSearchBar });
}
render() {
if (this.state.showSearchBar) {
return (
<Header>
<View style={styles.searchHolder}>
<Item style={styles.searchBar}>
<Icon name="ios-search" />
<Input placeholder="Search" />
</Item>
<Button style={styles.searchButton} onPress={this.searchBarButton}>
<Text>Search</Text>
</Button>
</View>
</Header>
);
}
return (
<Header>
<Button onPress={() => this.searchBarButton()} transparent>
<Icon name="search" style={styles.bigblue} />
</Button>
</Header>
);
}
So basically It is very fast initially , But when my scene contains lots of items in flat List , There is like 1 to 2 seconds delay between toggle.I guess its due to re-rendering all items in page.
So How can I toggle this in more easier and efficient way without Re rendering whole page without using state

I think you have to hide one of them by using style prop.
Just render both first, toggle one of them to be hidden(by using state),
<Header>
<View style={[this.state.showSearchBar && styles.hidden]}>Button</View>
<View style=[{!this.state.showSearchBar && styles.hidden}]>Icon</View>
</Header>
do not remove them from virtual dom(I don't know what to call it in mobile) completely

I'd recommend you to grab some UI library. Take a look at this: https://react-bootstrap.github.io/components.html#utilities
You can just trow you your searchbar code in this
<Collapse in={this.state.showSearchBar}>
...
</Collapse>
And everything is taken care of very efficiently.
You just need to trow your button in an operator {!showSearhBar && <Component/>}
Also use react dev tools to check what re-renders

Related

React Native Modal Positioning

I'm using the Modal built into React Native (and specifically I'm using the React Native Paper variant). By default this seems to open in the middle of the screen. However if you're doing some text input in the Modal then it would be more useful if it opened either at the top of the screen, or was aware of the keyboard. However I can't find a way to get this to work.
My (simplified) modal code is:
<Portal>
<Modal visible={visibleModalNew} onDismiss={closeModalNew} contentContainerStyle={styles.modalContainer} >
<View>
<Title>New</Title>
<View>
<TextInput
mode="outlined"
label="Data"
style={{alignSelf:'center', width:'95%'}}
defaultValue={newData}
onChangeText={newData=> setNewData(newData)}
onSubmitEditing={() => handleDone()}
/>
<Button onPress={() => doSomething()}>Do something</Button>
</View>
</View>
</Modal>
</Portal>
Ah, figured out a way round. I wrapped the modal in a KeyboardAwareView, removed the visible prop from the modal, and then wrapped it all in a conditional render and put the visible prop there instead. Seems to work as hoped.

Trying to use two props in custom defined component in react native, but it doesn't work

I am adding two props (textProp & imgProp) to my custom component, but I keep on getting this error <Image> component cant contain children. This is what I have soo far
function TextImg(textprop, imgprop) {
return(
<div>
<div>
<Text>{textprop.text}</Text>
</div>
<div>
<Image source={imgprop.imageUri}>!</Image>
</div>
</div>
);
}
Can anyone help me regarding this, Thanks!
Images (img) are considered empty elements and are self-closing, and required to be per the html spec.
https://developer.mozilla.org/en-US/docs/Glossary/Empty_element
The react native Image has the same restriction.
They can't wrap anything or have any children nodes. The "!" is the issue.
<Image source={imgprop.imageUri}>!</Image>
Try instead
<Image source={imgprop.imageUri} />
If you need to display an "!" then it'll have to be outside the image.
if you need to show "!" in image,
Try
<View>
<Image source={img} />
<Text
style={{
position: "absolute",
// some stylng
}}
>
!
</Text>
</View>

can i reuse a single instance of a component at multiple places on a screen in react?

I have this application that i am writing in react-native, where i have this screen which displays around 50-100 images and some action buttons associated with them, including a pop-up menu(one associated with each of them). Is there a way that i can use same pop-up menu(same instance) for all images?
<View>
// react-native-paper Card Component
<Card style={styles.card}>
<Card.Content style={styles.cardContent}>
<Card.Cover
style={{ height: 60, width: 60 }}
source={
item.avatar ||
(item.gender === 'male'
? require('../../assets/male.jpeg')
: require('../../assets/female.jpeg'))
}
/>
<Caption style={styles.title}>{item.name}</Caption>
</Card.Content>
<Card.Actions>
<Avatar.Text
style={{ backgroundColor: 'skyblue' }}
size={24}
label={`#${item.id}`}
/>
// react-native-paper Menu Component
// can i somehow use a single component for all cards?
<Menu
visible={this.state.visible}
onDismiss={this._closeMenu}
anchor={
<IconButton
icon="menu"
theme={theme}
size={20}
onPress={() => console.log('Pressed')}
/>
}
>
<Menu.Item onPress={() => {}} title="Item 1" />
<Menu.Item onPress={() => {}} title="Item 2" />
<Divider />
<Menu.Item onPress={() => {}} title="Item 3" />
</Menu>
</Card.Actions>
</Card>
.
.
//same card multiple times
.
.
</View>
You can extract the Menu component into your own custom component and then reuse it in your cards. This means you only need to define your Menu once and then use that one component multiple times (which will create a separate instance of the Menu for each card, acting independently of each other).
You can also do the same for your Card component which means you don't have to define the same thing multiple times. Will make your code much cleaner and more useable (your methods you define in your components will only execute for that instance of the component, not on a global level as your above code will - e.g. this._closeMenu will only execute for the Menu instance that it's defined in)
Take a look here for how to go about extracting and reusing your components - https://caster.io/lessons/react-native-extracting-and-writing-react-native-components

Changing Visibility of a button inside the component dynamically

I am using React-Navigation but I guess You don't really need to have a prior knowledge about it.
So I have a header Component which looks like this
const Header = (props) => {
return (
<View style={headerContainer}>
<View>
<Button onPress={() => props.navigation.navigate('Home')}
title="Go Back"/>
</View>
<Text style={header}> Knicx
<Text style={headerSecondary}> Crypto Ticker </Text>
</Text>
</View>
)
}
Now, In the above notice the button, Which I am currently showing on all the pages
<Button onPress={() => props.navigation.navigate('Home')}
title="Go Back"/>
But I don't want it to be there on some specific pages, like HomeScreen to say the least.
Now, One solution is to remove the <Header /> component in my homepage, Copy the above code snippet, past it in my HomeScreen and remove the Component ( sort of like hardcoding ) or two create two Header component, one with button and one without button
[Question:] But I was thinking if we could toggle the visibility of button dynamically or stack it on the top of <Header /> ? Can someone please tell me how can we do it? (No, We can set the opacity of the button to zero and change it whenever we need it)
[Update:] We can use redux to manage/pass the state but the problem is that in React-native we do not have display: none and I don't want to change use the opacity
Send showHomeButton: boolean as a prop to header
const Header = props => (
<View style={headerContainer}>
{this.props.showHomeButton && (
<View>
<Button onPress={() => props.navigation.navigate('Home')} title="Go Back" />
</View>
)}
<Text style={header}>
{' '}
Knicx
<Text style={headerSecondary}> Crypto Ticker </Text>
</Text>
</View>
);

react-native onPress() toggles automatically on a loop component rendering

I'm looping through a native-base <Card dataArray={data} /> component rendering some components with Buttons. It was working alright (Listed all components as expected) but I soon added an onPress event to the Button and got an automatic onPress bug, weird enough it runs (clicks hence runs the bounded function) only once while components suppose to render with those buttons are many.
//- Inside constructor I bind testLogs
this.testLogs = this.testLogs(this);
//- Outside render...
testLogs(value) {
console.log(value);
}
//- Inside return of render()
<Card dataArray={devices}
renderRow={(theme) =>
<CardItem>
{(theme.picture) ?
<Thumbnail size={100} source={theme.picture} />:
<Thumbnail size={100} source={defaultImage} />
}
<Text style={{fontSize: 16}}> {theme.name} </Text>
<Button primary style={{marginRight: 10}}> Command </Button>
<Button success onPress={this.testLogs} > Edit </Button>
</CardItem>
}>
</Card>
I should also say all the rendered components don't run the onPress={this.testLogs} bound function when i click them after they render.
What could be triggering this? Or is loop rendering not the best approach to this?
Thank you.
Use onPress={this.testlogs.bind(this)}

Resources