React-native passing component to another - javascript

I would like to pass one React component to my CustomTab component.
So i have something like this :
const FirstRoute = () => <View style={[ styles.container, { backgroundColor: '#ff4081' } ]} />;
const SecondRoute = () => <View style={[ styles.container, { backgroundColor: '#673ab7' } ]} />;
export default class Profile extends Component {
_renderScene = SceneMap({
first: FirstRoute,
second: SecondRoute,
});
render() {
return (
<CustomTab scenes={this._renderScene}/>
);
}
In my CustomTab i have :
export default class CustomTab extends React.Component {
_renderScene = this.props.scenes;
render() {
return (
<TabViewAnimated
style={styles.container}
navigationState={this.state}
renderScene={this._renderScene}
but this is not working, looks like passed parameter is wrong .It is possible to achieve that ?
Thx for any help.

You should set _renderScene property in constructor or other react component life cycle methods like.
constructor(props) {
super(props);
this._renderScene = this.props.scenes;
}

Your syntax is wrong, you need to assign _renderScene variable in render or constructor however there is not need for you to assign this.props.scenes to another class variable you could just directly use it
export default class CustomTab extends React.Component {
render() {
return (
<TabViewAnimated
style={styles.container}
navigationState={this.state}
renderScene={this.props. scenes}

Related

How to call function from different component bound to flatlist in React Native

I am creating a chat application in React Native that receives different "message types" as a response. One of them contains an array of buttons that I am currently rendering in a Flatlist in Component "ChatQuickReply" that looks like this:
import React from "react";
import {
StyleSheet,
FlatList,
View,
TouchableOpacity,
Text
} from "react-native";
class ChatQuickReply extends React.Component {
constructor(props) {
super(props);
}
renderItem({ item }) {
return (
<TouchableOpacity onPress={this._onPressQuickReply}>
<View style={styles.quickButton}>
<Text style={styles.quickButtonText}>{item.title}</Text>
</View>
</TouchableOpacity>
);
}
_onPressQuickReply = () => {
alert(Hello);
};
render() {
return (
<View>
<FlatList
data={this.props.buttons}
keyExtractor={(item, index) => "key" + index}
renderItem={this.renderItem}
/>
</View>
);
}
}
I am rendering this component in a different component also in a Flatlist which works fine.
The problem is, that I am not able to call the function that I am assigning to my TouchableOpacity. How can I call this function from a different component?
I think, what you can try to trigger onPress event for your TouchableOpacity component.
You need ref for this.
ref={touchableOpacity => this._touchableOpacity = touchableOpacity}
then when you want to launch onPress without clicking it just call
this._touchableOpacity.touchableHandlePress();
Depending on the relationship between both components, if the ChatQuickReply reply is a parent component, you can pass the function in the child as props and call it.
import React from "react";
class ChatQuickReply extends React.Component {
renderItem({ item }) {
return (
<TouchableOpacity onPress={this._onPressQuickReply}>
<View style={styles.quickButton}>
<Text style={styles.quickButtonText}>{item.title}</Text>
</View>
</TouchableOpacity>
);
}
_onPressQuickReply = () => {
alert(Hello);
};
render() {
return (
<View>
<FlatList
data={this.props.buttons}
keyExtractor={(item, index) => "key" + index}
renderItem={this.renderItem}
/>
**<ChildComponent clickParentFunction={this._onPressQuickReply} />**
</View>
);
}
}
class ChildComponent extends React.Component {
onClick = () => {
const {clickParentFunction} = this.props
clickParentFunction() // We can call it here
}
// We create a trigger to the onclick
}
or you can take the _onPressQuicklyReply function to the component that renders both components and pass it in to make it more generic
import OtherComponent from './Othercomponent';
class ParentComponent {
_onPressQuickReply = () => {
alert(Hello);
}
return (
<View>
<ChatQuicklyReply onParentFunction={this._onPressQuickly}>
<OtherComponent onParentFunctionCall={this._onPressQuickly} />
</View>
)
}

Can we use this.props.map as well as this.props.navigation in single class to navigate to another screen

I have used this.props.maps as well as this.props.navigation which is showing an error:
this.props.navigation.navigate is undefined object
Trying to navigate to another page by rendering the firebase database but getting error but the same code i tried by simple creating a view and navigating to another page then it is working
export default class ItemComponent extends Component {
constructor(props) {
super(props);
// need to bind `this` to access props in handler
this._onEditLibrary = this._onEditLibrary.bind(this);
}
static propTypes = {
items: PropTypes.array.isRequired
};
_onEditLibrary=()=> {
this.props.navigation.navigate('EditLibrary');
};
render() {
return (
<View style={styles.itemsList}>
<TouchableOpacity onPress={this._onEditLibrary}>
{this.props.items.map((item, index) => {
return (
<View key={index}>
<ImageBackground source={item.Image} style={ { height:150, width:150}}>
<Text style={styles.itemtext}>{item.Name}</Text>
</ImageBackground>
</View>
)
})
}
</TouchableOpacity>
</View>
);
}
}
Need to navigate to another page
Try this out
export default class ItemComponent extends Component {
constructor(props) {
super(props);
// need to bind `this` to access props in handler
this._onEditLibrary = this._onEditLibrary.bind(this);
}
static propTypes = {
items: PropTypes.array.isRequired
};
_onEditLibrary=()=> {
this.props.navigation.navigate('EditLibrary');
};
render() {
return (
<View style={styles.itemsList}>
{this.props.items.map((item, index) => {
return (
<TouchableOpacity key={index} onPress={this._onEditLibrary}>
<ImageBackground source={item.Image} style={ { height:150, width:150}}>
<Text style={styles.itemtext}>{item.Name}</Text>
</ImageBackground>
</TouchableOpacity>
)
})
}
</View>
);
}
}

Passing object to reusable view get error: null is not object (evaluating ...)

I create a Component which is getting data from server then shows data on the screen. The screen look good when I use react-native views directly.
After that, I refactor the code to make it reusable by moving a snippet of code to a new component (TwoGroupItemsView):
export class MainComponent extends Component {
componentDidMount() {
return fetch('https://mycompany.com/items')
.then(res => res.json())
.then(json => {
this.setState({
isLoading: false,
items: json.data,
}, function(){
});
}
}
render() {
return (
<View>
<View>
{
this.state.items != null &&
<TwoGroupItemsView title={'Group 1'} items={this.state.items}/>
}
</View>
</View>
);
}
}
class TwoGroupItemsView extends View {
constructor(props) {
super(props);
}
render() {
return (
<View style={{marginTop: 16}}>
//... FlatList for items array
</View>
)
}
}
I always get:
TypeError: null is not an object
When evaluating 'this.state.items'.
Can you show me the way to create my own reusable views?
Your state is being set asynchronously. Try explicitly initializing it before the Promise resolves. Some possibilities below.
Declaring the initial state:
export class MainComponent extends Component {
state = {
isLoading: true, // sample values
items: null
}
Or setting in the constructor:
export class MainComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true, // sample values
items: null
};
}
Or strengthening the guards:
render() {
return (
<View>
<View>
{
this.state && this.state.items != null &&
<TwoGroupItemsView title={'Group 1'} items={this.state && this.state.items}/>
}
</View>
</View>
);
}
Re write your render function.
render() {
return (
<View>
<View>
{
this.state.items ?
<TwoGroupItemsView title={'Group 1'} items={this.state.items}/> : null
}
</View>
</View>
);
}

Passing a value via props onPress

I know we can call the function like {this.props.onPress}, can we pass value using this callback too? Default object is passed but I want to pass a string value using this function. Is this possible, I'm posting my code to clear the situation.
import Cbuttons from './../utils/CustomButtons'
class MainScreen extends Component {
_onBtnClick = event => {
console.log("Click on Button");
}
render() {
return (
<View style={customStyles.mainContainer}>
<Cbuttons btnName="MainScreen" onPress={this._onBtnClick}/>
<Cbuttons btnName="ScreenTwo" onPress={this._onBtnClick}/>
<Cbuttons btnName="ScreenThree" onPress=
{this._onBtnClick}/>
</View>
);
}
}
export default MainScreen;
while inCustom Buttons clsss
class MyButtons extends Component {
constructor(props){
super(props);
this.state={btnName:this.props.btnName};
}
render(){
return(
<TouchableOpacity onPress={this.props.onPress} >
<Text style={yourStyles.buttonText}> {this.props.btnName}</Text>
</TouchableOpacity>
);
}
}
export default MyButtons;
I want to return btnName back via this.props.onPress
<Cbuttons btnName="MainScreen" onPress={ () => { this._onBtnClick(this.props.btnName)}/>
Turn that field into a function which calls the _onBtnClick function normally with a parameter.
Then you would reflect that in the _onBtnClick() method:
_onBtnClick = buttonName => {
console.log(`Click on Button ${buttonName}`);
}
This solved my problem, Thanks #mcpolo
class MyButtons extends Component {
render(){
return(
<TouchableOpacity onPress={()=>{this.props.onPress(this.props.btnName)}} >
<Text style={yourStyles.buttonText}> {this.props.btnName}</Text>
</TouchableOpacity>
);
}
}

how bind correctly in react-native?

I'm try to update the state from a function, but I don't find the correct form to bind the scope. My code (I am working with native-base components):
export default class MenuScreen extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
_renderRow() {
return (
<ListItem avatar onPress={() =>
ActionSheet.show(
{options: BUTTONS
}, buttonIndex => { setState({ clicked: BUTTONS[buttonIndex]})}
)}
>
</ListItem>
);
}
render() {
return (
<SectionList
sections={[...]}
renderItem={this._renderRow}
/>
);
}
First option, bind it in constructor
Example
constructor(props) {
super(props);
this.state = {};
this._renderRow = this._renderRow.bind(this);
}
Second option, bind it inline
Example
<SectionList
sections={[...]}
renderItem={this._renderRow.bind(this)}
/>
Third option, use arrow functions
Example
renderRow = () => {
return (
<ListItem avatar onPress={() =>
ActionSheet.show(
{options: BUTTONS
}, buttonIndex => { this.setState({ clicked: BUTTONS[buttonIndex]})}
)}
>
</ListItem>
);
}
My recommendation would be to read this:
https://medium.freecodecamp.org/react-binding-patterns-5-approaches-for-handling-this-92c651b5af56
Helps a lot with understanding binding options you have and why one or other might be better in your case.
I suggest to go with binding in constructor:
export default class MenuScreen extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.handleChange = this.handlePress.bind(this);
}
...
self mental note, "Bind is dummy if I not use the context of the function"
export default class MenuScreen extends React.Component {
constructor(props) {
super(props);
this.state = {};
**this._renderRow = this._renderRow.bind(this);**
}
_renderRow() {
return (
<ListItem avatar onPress={() =>
ActionSheet.show(
{options: BUTTONS
}, buttonIndex => { **this.**setState({ clicked: BUTTONS[buttonIndex]})}
)}
>
</ListItem>
);
}
render() {
return (
<SectionList
sections={[...]}
renderItem={this._renderRow}
/>
);
}

Categories

Resources