React Native : Regarding State and Callback handlers - reactjs

So I am still learning React Native and I am trying to build a very simple app to understand state, events in React Native.
Here in this app I display a button titled "first" as soon as the app is rendered on the screen.
Upon clicking that button a modal is displayed. This modal contains a button titled "second".
The objective is to hide the modal upon "onPress" of the "second" button.
Thsi is my code.
import React from 'react';
import { StyleSheet, Text, View, Button, Modal } from 'react-native';
export default class App extends React.Component {
constructor(props) {
super(props);
this.showModal = this.showModal.bind(this);
}
state = {
modalVisible: false,
}
hideModal = () => {
console.log("Btnpress pressed");
this.setState({modalVisbile: false});
}
showModal() {
console.log("BtnPress1 pressed");
this.setState({modalVisible: true});
}
render() {
return (
<View style={styles.container}>
<Button title="first"
onPress={this.showModal}
disabled={this.state.modalVisible} />
<Modal
animationType= "slide"
transparent= {false}
visible={this.state.modalVisible}
>
<Button
title="second"
onPress={this.hideModal}
disabled={!this.state.modalVisible}
/>
</Modal>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
What Happens
a) There are no errors.
b) The app is rendered successfully and display the button "first".
c) When the "first" button is clicked, the second button("second") contained in the modal is rendered as expected.
d) But when the "second" button is clicked the "first" button is not rendered.
My understanding is that upon "onPress" event on "second" button the below callback is invoked which changes the state.
onPress={this.hideModal}
After changing that state (which would now be modalVisible = false) the button titled "first" will be rendered. But this is not happening.
Can some one tell em what I am doing wrong ?

In your code, you misspelled visible, if you correct the spelling, it looks like it will work
hideModal = () => {
console.log("Btnpress pressed");
this.setState({modalVisible: false}); /*you had modalVisbile*/
}

Related

How to add event handlers to none React parts of the page

I have a dropdown box in a react component that expands/contracts to show the content. If the user clicks off the box (almost anywhere on the page), I want the box to contract. Without React, I would use an event handler to run some jQuery to contract the box, however my understanding is that this will cause issues since the jQuery will have changed the DOM and React will not be aware of it.
Can someone please explain how to add an event handler to an element that will cause a function inside React to run and contract the box.
I have tried the code below, however when I try to add the event listener i get the message that "this.myFunction" is undefined in my AddListener function.
import './App.css';
import React, { Component } from 'react';
//function App() {
class App extends Component {
constructor(props) {
super(props);
this.myFunction = this.myFunction.bind(this);
this.removeListener = this.removeListener.bind(this)
}
myFunction() {
alert("Hi user!");
}
removeListener() {
document.getElementById('CLICKER').removeEventListener("click", this.myFunction, false);
console.log('Removed');
}
addListener() {
document.getElementById('CLICKER').addEventListener('click', this.myFunction);
console.log('Added');
}
render() {
return (
<div className="App">
<div onClick={this.removeListener} style={{ backgroundColor: 'red' }}>
Remove Event Listener
</div>
<div onClick={this.addListener} style={{ backgroundColor: 'blue' }}>
Add Event Listener
</div>
</div>
);
}
}
export default App;
I realised i needed to add the constructor:
this.addListener = this.addListener.bind(this);

Custom Read More in React.js

As you can see this image, "+Las mor" is a "see more" button, which when clicked expands the whole paragraph written above.
I need React code for this to be functional. Any help will be appreciated.
I am also attaching the code upon which this functionality is to be applied.
<section id="section-2">
<h4>Om mig</h4>
<p className="para">
{about}
</p>
</section>
<p style={{color:'#d39176'}}>
<img src={plus1} />
Läs mer
</p>
You probably want a button that toggles the state of expanded text onClick. Upon hitting the button you would set the state to the opposite of what it was. Here's a working example I wrote with React and Reactstrap. I just tested it locally. Here's a video demo of what you will see: https://screencast.com/t/in5clDiyEcUs
import React, { Component } from 'react'
import { Container, Button } from 'reactstrap'
class App extends Component {
constructor(props) {
super(props)
this.state = {
expanded: false //begin with box closed
}
}
//function that takes in expanded and makes it the opposite of what it currently is
showButton = () => {
this.setState({ expanded: !this.state.expanded })
}
render() {
const { expanded } = this.state
return (
<Container style={ { justifyContent: 'center', alignItems: 'center' } }>
<div>Always visable text.</div>
<Button onClick={ this.showButton }>Expand</Button>
{
expanded && //show if expanded is true
<div>Extended Text Here</div>
}
</Container>
)
}
}
export default App

Semantic UI React: how to add a transition to Popup?

I'm building a "hovering" menu, using semantic-ui-react's Popup, and want to add a simple show-hide transition, how it can be done?
this is probably coming in too late for this specific OP, but might be useful for someone else trying to figure same out.
I believe you can use the TransionablePortal as shown in the example. Just for fun, I adapted that example to what I think you are trying to do:
import React, { Component } from 'react'
import { Button, Menu, TransitionablePortal } from 'semantic-ui-react'
export default class TransitionablePortalExamplePortal extends Component {
state = { open: false }
handleOpen = () => this.setState({ open: true })
handleClose = () => this.setState({ open: false })
render() {
const { open } = this.state
return (
<TransitionablePortal
closeOnTriggerClick
onOpen={this.handleOpen}
onClose={this.handleClose}
transition={{animation: "fade left", duration: 500 }}
openOnTriggerClick
trigger={
<Button circular basic
icon="ellipsis vertical"
negative={open}
positive={!open}
/>
}
>
<Menu vertical style={{ right: '1%', position: 'fixed', top: '0%', zIndex: 1000}}>
<Menu.Item>Menu Item 1</Menu.Item>
<Menu.Item>Menu Item 2</Menu.Item>
</Menu>
</TransitionablePortal>
)}}
You should be able to make the transition use onMouseEnter and onMouseLeave if you want same transition to be on hover, instead of on click.
You can find in their official documentation example where you can make custom style for popup
import React from 'react'
import { Button, Popup } from 'semantic-ui-react'
const style = {
borderRadius: 0,
opacity: 0.7,
padding: '2em',
}
const PopupExampleStyle = () => (
<Popup
trigger={<Button icon='eye' />}
content='Popup with a custom style prop'
style={style}
inverted
/>
)
export default PopupExampleStyle
You can try to add transition property here

Hide and show reactnavigation headers onPress

I am using React Navigation and want to Hide/Show the header onScroll or onPress. Is this pseudo code the proper way to go about it? Also, could you please advice on what props do I need to pass and how do I pass them from the _handleHide and _handleShow functions?
import React, { Component } from 'react'
import { View, Text, StyleSheet, Button} from 'react-native'
class MyApp extends Component {
static navigationOptions = {
title: 'MyTitle' // this is the header I want to hide/show
}
constructor () {
super(props);
this.state = {
showHeader: false
}
this._handleHide = this._handleHide.bind(this);
this._handleShow = this._handleShow.bind(this);
}
_handleHide(){
// how do i code this to hide the header?
}
_handleShow(){
// how do i code this to show the header?
}
render(){
return(
<View style={styles.container}>
<Button onPress={this._handleHide} title="Hide Header" />
<Button onPress={this._handleShow} title="Show Header" />
</View>
)
}
}
const styles = StyleSheet.create({
container:{
flex: 1, justifyContent: 'center', alignItems: 'center'
}});
export default MyApp;
Many thanks.
UPDATE 1
_handleHide(){
this.setState({showHeader: false});
}
_handleShow(){
this.setState({showHeader: true});
}
There is no on state change for that post I mentioned. Not near a computer right now but I would add a state in the constructor called showHeader: true and in _handleHide and _handleShow, change the state of showHeader.
Then from the post Dynamically hide/show header in react-native:
this.props.navigation.setParams({
header: this.state.showHeader ? whatever-you-want : null
})

React Native : undefined is not an object

I am currently learning React Native.
I just a built a very simple app to test out the Button component.
When I click on the button component the console log is printed as expected.
But after printing out the console log it pops out the following error.
**undefined is not an object (evaluating '_this2.btnPress().bind')**
I am not sure what is wrong ?
Can anyone let me know what I am doing wrong ?
import React from 'react';
import { StyleSheet, Text, View, Button } from 'react-native';
export default class App extends React.Component {
btnPress() {
console.log("Fn Button pressed");
}
render() {
return (
<View style={styles.container}>
<Button title="this is a test"
onPress={()=> this.btnPress().bind(this)} />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
You are invoking the function instead of passing a reference through bind.
loose the ().
And you should not wrap it with an arrow function as bind is already returning a new function instance
onPress={this.btnPress.bind(this)} />
By the way, this will return and create a function instance on each render, you should do it once in the constructor (which runs only once):
export default class App extends React.Component {
constructor(props){
super(props);
this.btnPress = this.btnPress.bind(this);
}
btnPress() {
console.log("Fn Button pressed");
}
render() {
return (
<View style={styles.container}>
<Button title="this is a test"
onPress={this.btnPress} />
</View>
);
}
}
Or use an arrow function which uses a lexical context for this:
export default class App extends React.Component {
btnPress = () => {
console.log("Fn Button pressed");
}
render() {
return (
<View style={styles.container}>
<Button title="this is a test"
onPress={this.btnPress} />
</View>
);
}
}

Resources