1

I am working with react native and I want to pass function and some data from Component class to another Stateless class, but I could not make to passing function and data part.

Here you can see my Component class:

class Classroom extends Component {

    constructor(props, context) {
        super(props, context);



    };

    state = {
        isLightOn: false,
        title : "Turn light on "
    }

   onPress() {
       this.setState({isLightOn: !this.state.isLightOn})
       console.log(this.state.isLightOn)
       this.setState({title:this.state.isLightOn===false ?"Turn light off":"Turn light on"})

   }

    render() {
        return (
            <View style={styles.blue}>

                <LightBulb  isLightOn={this.state.isLightOn}> </LightBulb>
                <LightButton onPress={this.onPress} isLightOn={this.state.isLightOn} title={this.state.title} > </LightButton>


            </View>
        );
    }


}

Firstly, I want to pass isLightOn and title datas to my LightButton class (which mean to my stateless class). After that, I want to use onPress function inside of my Stateless class, but I cannot use. I am taking that error:

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

I also LightButton onPress={this.onPress} remove parenthesis, but still taking error.

Here is my my Stateless class

const LightButton = ({onPress,isLightOn,title}) => (


        <View style={styles.red}>


            <Button
                title= {title}
                onPress={() => {}

                }
            />
        </View>
)

I want to use onPress function and datas inside of the this class. As a result, How can I pass function and data to that class?

  • Can you show how you *were* using `onPress` in `LightButton`? My guess is you were doing it something like `onPress={onPress()}`? – Brian Thompson May 27 '20 at 13:16
  • I have an answer to a similar question: https://stackoverflow.com/a/51661103/2430549 "Correct way to share functions between components in React." There are actually two paradigms (to begin with!). Hope this helps! – HoldOffHunger May 27 '20 at 13:24

3 Answers3

1

The main issue here is that you need to declare onPress using an arrow function or bind it to the component's this value within the constructor. Otherwise it wouldn't have access to the correct this value. Other than that, the way you were passing props into components is perfectly fine.

I also merged your two set state calls in onPress to one as it's easier.

In LightButton, I set it up like this to pass the onPress function down to the button:

const LightButton = ({ onPress, isLightOn, title }) => (
  <div style={{backgroundColor:'red'}}>
    <Button title={title} onPress={onPress} />
  </div>
);

(I set it up using react, but the issues at hand are more of a JS issue than a React/ReactNative one, so the advice should still be valid :) )

const { Component } = React;
const View = 'div';
const Button = (({title,onPress})=><button onClick={onPress}>{title}</button>);

const LightBulb = ({ isLightOn }) => {
  return <div className={'LightBulb' + (isLightOn ? ' on' : '')} />;
};

const LightButton = ({ onPress, isLightOn, title }) => (
  <div style={{backgroundColor:'red'}}>
    <Button title={title} onPress={onPress} />
  </div>
);
class Classroom extends Component {
  state = {
    isLightOn: false,
    title: 'Turn light on ',
  };

  onPress=()=> {
    console.log(this.state.isLightOn);
    this.setState({
      title:
        this.state.isLightOn === false ? 'Turn light off' : 'Turn light on',
        isLightOn: !this.state.isLightOn
    });
  }

  render() {
    return (
      <div style={{backgroundColor:'blue'}}>
        <LightBulb isLightOn={this.state.isLightOn}> </LightBulb>
        <LightButton
          onPress={this.onPress}
          isLightOn={this.state.isLightOn}
          title={this.state.title}
        >Button</LightButton>
      </div>
    );
  }
}

ReactDOM.render(<Classroom />, document.querySelector('#root'));
.LightBulb {
  height: 50px;
  width: 50px;
  border-radius: 50px;
  background-color: black;
}
.LightBulb.on {
  background-color: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"/>
Zachary Haber
  • 10,376
  • 1
  • 17
  • 31
0

You can assign it like


const LightButton = ({onPress,isLightOn,title}) => (
  ...
  onPress={onPress}
  ...

or with an arrow function if you need to pass arg inside


onPress={()=>onPress(someArg)}

do notice that you either don't put () at all, or twice () => func() for not run the function while it is just loads and not clicked.

unrelated directly to your issue but something that you encounter is inside onPress by doing like so


 this.setState({isLightOn: !this.state.isLightOn})
 console.log(this.state.isLightOn)
 this.setState({title:this.state.isLightOn===false ?"Turn light off":"Turn light on"})

setState it is an async call, and therefore second setState usage not guaranteed to refer the state as you expect, use setState({ ... }, () => callback()) or all at one line and accords to prev state


 this.setState({isLightOn: !this.state.isLightOn, title: !this.state.isLightOn===false ?"Turn light off":"Turn light on"})
Hagai Harari
  • 2,767
  • 3
  • 11
  • 23
  • 1
    I think you're right about the async confusion, but I'm not sure it would solve the max update depth error. My guess is the error is related to the first section of your answer and they were most likely doing `onPress={onPress()}`. Once they clear up that error, the second part of your question will be helpful too. – Brian Thompson May 27 '20 at 13:26
-2
  1. First thing you did wrong is your state instantiating ! you need to instantiate your state in the constructor block like:
constructor(props, context) {
  super(props, context);
  this.state = { counter: 0 };
}
  1. onPress() you use this for your function which is not recommended in react native or any other language , those are dedicated functions and methods of React Native

  2. For passing a parameter or calling a function it is better to use these patterns ====>

onPress={() => urFunction()} with parenthesis or

onPress={urFunction} without parenthesis

Do the modifications I hope it helps <3

Brian Thompson
  • 13,263
  • 4
  • 23
  • 43
Amir Doreh
  • 1,369
  • 1
  • 13
  • 25