简体   繁体   中英

How to pass function and data from component class to stateless class in React Native?

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?

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"/>

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"})
  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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM