Export functions out of react native components - reactjs

I just want to export a function to an actions.js file but i cannot get to work.
This is the working base:
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
visible: false
}
}
onOpen = () => {
this.setState({visible:true});
console.log(this.state.visible);
}
render() {
return (
<View style={styles.container}>
<Button onPress={()=>{this.onOpen();}}>More</Button>
</View>
);
}
}
And now i tried this, which gives me an error when i press the button:
Error:
Unhandled JS Exception: _this.setState is not a function. (In '_this.setState({ visible: true })', '_this.setState' is undefined)
Code:
let onOpen = () => {
this.setState({visible:true});
console.log(this.state.visible);
}
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
visible: false
}
this.onOpen = onOpen.bind(this);
}
render() {
return (
<View style={styles.container}>
<Button onPress={()=>{this.onOpen();}}>More</Button>
</View>
);
}
}

You cannot use the 'this' keyword outside the class Component. you cannot change the state of the component from outside the class.
More details here:
Change state Outside Component
Further, If you want to change the state of the component outside a class, make use of redux state.
Redux JS

The problem with your code is that you've define onOpen outside your class and you want to access setState function of the Component. I don't know why one would want to do this because onOpen belongs to class. But still if you want to put this outside class. You can do this by following way:
let onOpen = ({setState}) => {
//retrieve setState here
setState({visible:true});
}
export default class HomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
visible: false
}
// You don't have to do this if onOpen is not in your class
//this.onOpen = onOpen.bind(this);
}
render() {
//send this.setState to onOpen
const that = this;
return (
<View style={styles.container}>
<Button onPress={()=>{onOpen({setState: that.setState});}}>More</Button>
</View>
);
}
}

Related

Call Child function from Parent React Native - TypeError cannot read property of null

I have a Parent Component which has a Filter Component and the Filter Component has a FilterBox Component with a button on it.
Parent > Filter > FilterBox
FilterBox has a button which on click calls onButtonPress Function.
I want to call this onButtonPress function from Filter Component.
Tried using refs also tried binding the function in constructor. Still getting errors.
class Filter extends Component {
constructor() {
super();
this.child = React.createRef();
}
render() {
return (
<View>
<FilterBox
//props
ref = {this.child}
/>
<TouchableOpacity
onPress={()=>this.child.current.onButtonPress()}/>
</View>
)
}
class FilterBox extends Component {
constructor() {
super();
this.onButtonPress = this.onButtonPress.bind(this);
}
onButtonPress = () =>{
console.log("Hi")
}
}
I get a cannot read property 'onButtonPress' of null
You can do the following. I reproduce it in react so convert buttons to TouchableOpacity and onPress to onClick.
What it does is pass a function from filter to filterbox as a prop and when you call that function from componentDidMount of filterbox it set the state of filter component and give onButtonPress function to the this.state.propFunc.
class Filter extends Component {
constructor() {
super();
this.child = React.createRef();
this.state = {
propFunc: null
}
this.funcToPass = this.funcToPass.bind(this)
}
funcToPass(fn) {
this.setState({ propFunc: fn })
}
render() {
return (
<div>
<FilterBox
funcToPass={this.funcToPass}
/>
{this.state.propFunc != null && <button onClick={this.state.propFunc} />}
</div>
)
}
}
class FilterBox extends Component {
constructor() {
super();
}
onButtonPress = () => {
console.log("Hi")
}
componentDidMount() {
this.props.funcToPass(this.onButtonPress)
}
render() {
return (
<div>
</div>
)
}
}

React Native Show/Hide View

I have a file called test.js. It has two Classes A and B. In class B I have a button hide view.
What I want is when I click on hide view button then it should toggle(show/hide) the view of class A without loading.
How can I do this?
You can use this example:
export default class A extends Component {
constructor(props){
super(props)
this.state = {showComponmentB: true}
}
_toggleShow = () => {
this.setState({showComponmentB: !this.state.showComponmentB})
}
render() {
return (
<View style={styles.container}>
{this.state.showComponmentB && <B/>}
<Button title="toggle button" onPress={this._toggleShow}/>
</View>
);
}
}
export class B extends Component {
render() {
return (
<SomeView/>
);
}
}

undefined is not an object (evaluating 'this.props.navigation') react navigation

I'm using React Stack Navigator in React Native App. I have a problem with the navigation props.
Here is my component where I call my navigate method.
class CommandsList extends React.Component {
constructor(props){
super(props);
}
addCommand(){
this.props.navigation.navigate("CreateCommand");
}
render() {
return (
<SafeAreaView style={{flex:1}}>
<MyList itemsUrl="http://localhost:9000/commands"/>
<Button title="Ajouter" onPress={this.addCommand}></Button>
</SafeAreaView>
);
}
}
export default StackNavigator({
CommandsList : {
screen : CommandsList,
},
});
And my App.js
const RootStack = StackNavigator(
{
CommandsList: {
screen: CommandsList,
},
CreateCommand: {
screen: CreateCommand,
}
},
{
initialRouteName: 'CommandsList'
}
);
export default class App extends React.Component {
render() {
return <RootStack/>;
}
}
I don't understand why I have an error on navigate methods. :/
You need to bind your reference either using bind in the constructor or by using the fat arrow function to reference this to the context
addCommand = () => {
this.props.navigation.navigate("CreateCommand");
}
or
constructor() {
super()
this.addCommand = this.addCommand.bind(this);
}
Also you may check this article

How to fire this function for my component (React Native)?

I have this piece of code of a component that
class List extends Component {
...
render() {
...
return
<TouchableHighlight onPress={()=>this.props.clearFilter()}>
</TouchableHighlight>
...
}
...
}
The parent:
class Nav extends Component {
...
// render implements renderscene for navigator
renderScene(route, navigator){
...
return (
<List
navigator={navigator}
clearFilter={this.props.clearFilter}
ref={component => this._list = component}/>
);
}
and:
export default class App extends Component {
applyfilter(){
//...
}
constructor(props){
...
this.applyfilter = this.applyfilter.bind(this);
}
clearFilter(){
this.setState(
{
_filter:null,
_filterValue:"",
}, ()=>{this.applyFilter();}
);
_renderScene = ({ route }) => {
return <Nav ref={component => this._nav = component} clearFilter={this.clearFilter.bind(this)}/>;
...
}
So I am passing the clearFilter() function along from App to Nav, and Nav passes it on to List. When List's button is pressed, I want the clearFilter() of App to fire, but for it does not compute as a function for some reason.
I am getting undefined is not a function (evaluating '_this3.applyFilter()') every time the button is pressed.
How to fire clearFilter for App from the button of List?
Just a typo mistake: You're creating the function as applyfilterbut you're invoking it as applyFilter inside your clearFilter function. That's why it's throwing an error that it's undefined.
Assuming that you aren't missing some code here, this.applyfilter seems to be not defined anywhere.
Your code is not clearly formatted. looks like you have declared applyFilter outside the class. define it after constructor inside the class.
Personally I prefer using clearFilter={()=> {this.clearFilter()}} instead of clearFilter={this.clearFilter.bind(this)}
Same for applyFilter.
class Button extends Components {
render(){
return(
<TouchableOpacity
onPress={()=>{ this.props.clearFilter() }}
>
</TouchableOpacity>
);
}
}
class List extends Components {
render(){
return(
<Button
clearFilter={()=>{ this.props.clearFilter() }}
/>
);
}
}
export default class Mainapp extends Components {
constructor(props){
super(props);
this.state = {};
}
clearFilter(){
//// do something
this.applyFilter();
}
applyFilter(){
//// do something
}
render(){
return(
<View>
<List
clearFilter={()=>{ this.clearFilter() }}
/>
</View>
);
}
}

Calling a React function PropType from outside the class definition

I have the following React Component..
import React, { Component,PropTypes } from 'react';
import RequestListItem from '../RequestListItem';
import { ScrollView,Text,View } from 'react-native';
class RequestList extends Component {
render(){
return (
<ScrollView
onScroll={() => { console.log('onScroll!'); }}
automaticallyAdjustContentInsets={false}
scrollEventThrottle={200}>
{this.props.requests.map(mapRequests)}
</ScrollView>
);
}
}
RequestList.propTypes = {
requests: PropTypes.array.isRequired,
onRequestItemClick: PropTypes.func.isRequired
};
var mapRequests = (request, i) => {
<RequestListItem
id={request.id}
title={request.title}
onRequestItemClick={this.props.onRequestItemClick.bind(this)}
/>
};
export default RequestList;
The problem I am having is concerning the mapRequest function. I need to be able to invoke the onRequestItemClick that is passed in as a property to this component,but since this is defined outside of the class definition, it doesn't appear I have access to the properties. How do I accomplish what the code above is trying to do?
You can pass the callback to the mapRequests method, instead of trying to pull it directly from the props:
class RequestList extends Component {
constructor(props) {
super(props);
this.props.onRequestItemClick = this.props.onRequestItemClick.bind(this) // I'm not sure why your binding to this something you got from the props, so consider removing this line
}
render(){
return (
<ScrollView
onScroll={() => { console.log('onScroll!'); }}
automaticallyAdjustContentInsets={false}
scrollEventThrottle={200}>
{this.props.requests.map((request) => mapRequests(request, this.props.onRequestItemClick))} // the arrow function calls mapRequest, and passes the request and the callback
</ScrollView>
);
}
}
var mapRequests = (request, onRequestItemClick) => {
<RequestListItem
id={request.id}
title={request.title}
onRequestItemClick={onRequestItemClick}
/>
};
However, if you already use an anonymous function, you don't need mapRequests function anyway:
class RequestList extends Component {
constructor(props) {
super(props);
this.props.onRequestItemClick = this.props.onRequestItemClick.bind(this) // I'm not sure why your binding to this something you got from the props, so consider removing this line
}
render(){
return (
<ScrollView
onScroll={() => { console.log('onScroll!'); }}
automaticallyAdjustContentInsets={false}
scrollEventThrottle={200}>
{this.props.requests.map((request) => (
<RequestListItem
id={request.id}
title={request.title}
onRequestItemClick={this.props.onRequestItemClick}
/>
)}
</ScrollView>
);
}
}

Resources