Render React Component on Button Click Event - javascript

I have a minimalist landing page with two texts and one div, containing two buttons. On click of one of those buttons, I want to render the App component.
Here's what I've tried so far:
import React from 'react';
import App from '../App';
export default class Landing extends React.Component {
constructor(){
super();
}
launchMainWithoutProps = () => {
return (<App />)
};
showAppMain =() => {
console.log('Silk board clicked');
this.launchMainWithoutProps();
};
render() {
return (
<div className='landing'>
<div className="centered">
<div className="introText">
<h3>Welcome to KahanATM</h3>
<h5>A Simple Web App with React to find ATMs closest to you (3km radius) or from Silk Board Flyover</h5>
</div>
<div className="buttonsLayout">
<button
className='getLocation'
onClick={this.showAppMainWithLocation}>
Get My Location
</button>
<button
className='silkBoard'
onClick={this.showAppMain}>
Central Silk Board
</button>
</div>
</div>
</div>
);
}
}
But when the button is clicked only the log is shown in console. How can I do this with or without react-router as I think this is too small to implement routes in. Thanks.

Use a boolean flag in your state. When you click and execute showAppMain set your state variable to true, which causes your render function to return <App /> instead:
import React from 'react';
import App from '../App';
export default class Landing extends React.Component {
constructor() {
super();
this.state = {
shouldShowMain: false,
};
this.showAppMain = this.showAppMain.bind(this);
}
showAppMain() {
console.log('Silk board clicked');
this.setState({shouldShowMain: true});
};
render() {
if (this.state.shouldShowMain) {
return (<App />);
}
return (
<div className='landing'>
<div className="centered">
<div className="introText">
<h3>Welcome to KahanATM</h3>
<h5>A Simple Web App with React to find ATMs closest to you (3km radius) or from Silk Board Flyover</h5>
</div>
<div className="buttonsLayout">
<button
className='getLocation'
onClick={this.showAppMainWithLocation}>
Get My Location
</button>
<button
className='silkBoard'
onClick={this.showAppMain}>
Central Silk Board
</button>
</div>
</div>
</div>
);
}
}

Related

Creating a popup in ReactJs

I am new in ReactJs and trying to create a popup window through onclick event.
I am following this resource - https://dev.to/skptricks/create-simple-popup-example-in-react-application-5g7f
File - /src/components/feed.js
import React from 'react';
function feed (props) {
return (
<div className="card-header">
<h2>{props.firstname} {props.middleInitial} {props.lastname}</h2>
<h4 className="card-title">{props.gender}</h4>
</div>
<div className="card-footer">
<button onClick="" className="btn btn-secondary">Click To view Samples</button>
</div>
);
}
export default feed;
File - /src/app.js
import React, { Component } from 'react';
import './App.css';
import Header from './components/header.js';
import fetchfeed from './components/fetchfeed.js';
class App extends Component {
render() {
return (
<div>
<Header />
<div className="d-flex justify-content-center">
<fetchfeed />
</div>
</div>
);
}
}
export default App;
File - /src/components/fetchfeed.js
import React from 'react';
import axios from 'axios';
import Pagination from "react-js-pagination";
import feed from './feed.js';
class fetchfeed extends React.Component {
constructor(props) {
super(props);
this.state = {
feedDetails: []
};
this.fetchURL = this.fetchURL.bind(this);
}
fetchURL() {
axios.get(`/feed/`)
.then( response => {
..............
});
//Fetch the feed url and process the variables and setstate to feedDetails array.
}
componentDidMount () {
this.fetchURL()
}
populateRowsWithData = () => {
const feedData = this.state.feedDetails.map(feed => {
return <feed
key = {feed.id}
firstname = {feed.firstname}
middleInitial = {feed.middleInitial}
lastname = {feed.lastname}
dateOfBirth = {feed.dateString}
gender = {feed.gender}
/>;
});
return feedData
}
render(){
return (
<div >
{this.populateRowsWithData()}
</div>
);
}
}
export default fetchfeed;
I have already created Popup.js under /src/components and the required css for the popup as directed on reference link.
My question is where should I define the onclick function for popup?
Any help is highly appreciated. Thanks in advance.
As it says in the source you should do something like this in the component you want to show the popup in:
//This is the function
togglePopup() {
this.setState({
showPopup: !this.state.showPopup
});
}
// This is what you should do in the render method
{this.state.showPopup ?
<Popup
text='Click "Close Button" to hide popup'
closePopup={this.togglePopup.bind(this)}
/>
: null
}
As per my understanding, you are trying to customize the code in the tutorial according to your requirements. If you want to open the popup on click of the button "click to view samples", you should do two things first.
Define a function to trigger when button is clicked
Attach that function to the button
The following code demonstrates above steps.
import React from 'react';
function feed (props) {
function openPopup(){
//code relevant to open popup
}
return (
<div className="card-header">
<h2>{props.firstname} {props.middleInitial} {props.lastname}</h2>
<h4 className="card-title">{props.gender}</h4>
</div>
<div className="card-footer">
<button onClick={openPopup} className="btn btn-secondary">Click To view Samples</button>
</div>
);
}
export default feed;

Alter React parent component state

I am trying to create a simple SPA (without Router). It has also a simple structure: a component per section:
Home
Services
Products
Product
Modal
Contact us
As you can see the component Products has two sub-components Product and Modal. These are iterated so many times as JSON objects there are:
Products.js
import React, { Component } from "react";
import ReactHtmlParser from "react-html-parser";
import "./Products.css";
import { products } from "./products.json";
import Product from "./Product/Product";
import Modal from "./Modal/Modal";
class Products extends Component {
render() {
return (
<section id='products'>
<div className='container'>
<div className='row'>
{products.map(product => {
return (
<div>
<Product
image={"/img/" + product.image}
name={product.name}
target={product.target}
/>
<Modal
id={product.target}
title={product.name}
body={ReactHtmlParser(product.body)}
/>
</div>
);
})}
</div>
</div>
</section>
);
}
}
export default Products;
Each product has a More Info button what opens the modal and this has another button Budget ("Presupuestar"):
That function should "change the state" of Contact us component (a simple contact us form):
The component has the following code:
Contact.js
import React, { Component } from "react";
import "./Contact.css";
class Contact extends Component {
constructor() {
super();
this.state = { budget: "Contact" };
}
render() {
return (
<section id='contact'>
<div className='container'>
<div className='row'>
<div className='col-xs-12 col-md-6'>
<div className='contact-form'>
<form>
...
{/* Subject */}
<div className='form-group'>
<div className='input-group'>
<span className='input-group-addon' />
<input
type='text'
className='form-control'
id='subject'
aria-describedby='Subject'
placeholder='Subject'
readonly='readonly'
value={this.state.budget}
/>
</div>
{/* /form-group */}
</div>
{/* /Subject */}
...
</form>
</div>
</div>
</div>
</div>
</section>
);
}
}
I guess then I should create a function in the Modal component to trigger with an onClick="setSubject" in the Budget ("Presupuestar") button. What I don't know is how to alter the other component's state.
A quick summary: I have to make the following state update:
I was reading this similar question but I didn't get how to apply in my scenario. Any ideas?
I think you should either but the clickHandler function of the button in the App component that wrap the whole components and then pass it to the Products component then to Modal component but it's not a good practice,
Or you can use Redux a state management system that let you control your state through the whole app.
First of all, you don't need a function to change the state of another component. The smart way to do that is using an intermediary thing to connect 2 component together. There is two way to solve this problem.
The easiest way is you can transfer subject via URL (URL is "the intermediary thing"). When you click the button Presupuestar you can change URL to page contact like this:
/contact?subject=whatever you want
Then, at Contact component, you just need to parse URL to get subject (you can see this question to know how to parse from URL). You can see my example.
The second way is creating a service use singleton pattern to transfer subject from Modal to Contact form. You can see my example.
You can achieve this like this
Create a main app component which will contain all these these three comps
Add a function in app component "changeContacts"
Send it to both the product as well as contacts
Here is an explanation
class App extends Component {
render() {
return (
<div>
<Contact ref="contacts"/>
<Products changeContacts={this.changeContacts} />
</div>
);
}
changeContacts = (newState) => {
this.refs.contacts.changeState(newState)
};
}
class Contact extends Component {
state = { text:"Old Text" }
render() {
return ( <div style={{fontSize:50,backgroundColor:'red'}}>{this.state.text}</div> );
}
changeState = (newState) =>{
this.setState(newState);
}
}
class Modal extends Component {
render() {
return ( <div onClick={() => this.props.onClick({text:"New State Text"})}>This is a modal</div> );
}
}
class Products extends Component {
state = { }
render() {
return ( <div>
<h1>Products List</h1>
<Modal onClick={this.props.changeContacts} />
<Modal onClick={this.props.changeContacts}/>
<Modal onClick={this.props.changeContacts}/>
</div> );
}
}

React Loading New Page

I am trying to load a different React component using a button. It worked when doing it for authentication with GitHub using Firebase, but won't work for this page.
import React from 'react';
import './index.css';
import GamePage from '../Game';
class Home extends React.Component {
constructor(props){
super(props);
this.LoadGamePage = this.LoadGamePage.bind(this);
}
LoadGamePage() {
return(
<div>
<GamePage />
</div>
)
}
render(){
return(
<div className="home">
<h1>Home Page</h1>
<button onClick={this.LoadGamePage}>Play PIT</button>
</div>
)
}
}
export default Home;
Is there something wrong with my LoadGamePage function?
How it is supposed to work? You have an onclick handler, which calls a class method. That class method, called LoadGamePage, returns JSX. Okey, but what now? It is returned, but... not rendered. It won't display anywhere. What would I suggest you? Instead of returning the JSX inside that handler, I would set state and depending on state I would render the Game Page or not.
class Home extends React.Component {
constructor(props){
super(props);
this.state = {
gameVisible: false,
}
this.LoadGamePage = this.LoadGamePage.bind(this);
}
LoadGamePage() {
this.setState({ gameVisible: true });
}
render() {
if (this.state.gameVisible) {
return <GamePage />
}
return (
<div className="home">
<h1>Home Page</h1>
<button onClick={this.LoadGamePage}>Play PIT</button>
</div>
)
}
}

ReactJs component structure - Form inside modal

I am using the react-bootstrap Modal, Form and Button.
Desiring the functionality of clicking the button should open the modal with a form inside it. After filling out the form, one clicks a button (on the modal) and it validates the form data and posts it through a REST API.
I got far enough to figure out that my component split should be as follows:
A button component, a modal component and a form component.
What would be the correct way to structure these components in terms of props/state and placing the functions for validating the data? I am having trouble in understanding the child/parent relationship and when it's applicable
Components:
App Component: This is going to be the top level component
Button Component (If its just a button can also be
just a button):
If this is just a button you can keep this has a just a button in App component, if you are willing to reuse this with some custom element place it in a component.
Modal component: This is going to hold your modal like header,body,footer
Form component: This is a component which will hold the form and its validations.
Component Tree:
App Component will contain a state like showModal, we need to have a handler to set this value and this handler gets triggered when the button is clicked.
import FormModal from './FormModal';
class App extends React.Component {
state = {
showModal : false
}
showModalHandler = (event) =>{
this.setState({showModal:true});
}
hideModalHandler = (event) =>{
this.setState({showModal:false});
}
render() {
return (
<div className="shopping-list">
<button type="button" onClick={this.showModalHandler}>Click Me!
</button>
</div>
<FormModal showModal={this.sate.showModal} hideModalHandler={this.hideModalHandler}></FormModal>
);
}
}
Form Modal:
import FormContent from './FormContent';
class FormModal extends React.Component {
render() {
const formContent = <FormContent></FormContent>;
const modal = this.props.showModal ? <div>{formContent}</div> : null;
return (
<div>
{modal}
</div>
);
}
}
export default FormModal;
Hope that helped!
For basic pseudo code
Main Component:
import Modal from './Modal'
class Super extends React.Component {
constructor(){
this.state={
modalShowToggle: false
}
}
ModalPopUpHandler=()=>{
this.setState({
modalShowToggle: !modalShowToggle
})
}
render(){
return(){
<div>
<Button title='ModalOpen' onClick='this.ModalPopUpHandler'> </Button>
<ModalComponent show={this.state.modalShowToggle}>
</div>
}
}
}
ModalPopUp component:
import FormComponent from 'FormComponent'
class ModalComponent extends React.Component {
constructor(props){
super(props)
this.state={
modalToggle: props.show
}
}
render(){
if(this.state.modalToggle){
return(
<div>
<div className='ModalContainer'>
<FormComponent />
</div>
</div>
)
} else {
</div>
}
}
}
Form Component:
import Button from './Button'
class FormComponent extends React.Component {
constructor(){
this.state={
submitButtonToggle: true,
username: ''
}
}
inputHandler=(e)=>{
if(e){
this.setState({
username: e.target.value
})
}
}
render(){
return(
<div>
<input type='text' value='this.state.username' id='username' onChange='inputHandler' />
<Button title='Submit' disabled={this.state.username.length > 0}> </Button>
</div>
)
}
}
Above are the basic superComponent which we have rendered in app/main entry file.
And form || Modal Component. are the child component.
So in modal component I have called the same Form-component.
Here in Form-component input type handler, submit button is disabled from state.. with input string length we are handling its validation.
I hope it works for you.

React component re-renders endlessly with onClick

I want the onClick event of the button in result.js to render my Spinner component, and have so far (kind of) gotten it to do so. At the moment, Spinner mostly has some console.log() statements, and it keeps logging "Rendered spinner." endlessly after clicking the button, about once every second.
For the record, the returned paragraph isn't being displayed, but I haven't gotten around to debugging that yet. Also, I have excluded some code in Result.js that I think is irrelevant.
For now, I just want Spinner to only render once after pressing the button. Any tips?
result.js:
import React, { Component } from "react";
import { connect } from "react-redux";
import Spinner from "./spinner";
class UnboxResult extends Component {
constructor(props) {
super(props);
this.state = {
showSpinner: false
};
this.handleUnboxClicked = this.handleUnboxClicked.bind(this);
}
handleUnboxClicked(event) {
event.preventDefault();
console.log("Inside handleUnboxClicked");
this.setState({
showSpinner: true
});
}
render() {
return (
<section className="opening">
<div className="container">
<div className="row">
<button onClick={this.handleUnboxClicked}>UNBOX</button>
</div>
<div className="row">
{this.state.showSpinner ?
<Spinner items={this.props.unbox.items}/> :
null}
</div>
</div>
</section>
);
}
}
export default connect(state => ({
unbox: state.unbox
}))(UnboxResult);
spinner.js:
import React, { Component } from 'react';
class Spinner extends Component {
constructor(props) {
console.log("Before super");
super(props);
console.log("Ran constructor.");
}
render(){
console.log("Rendered spinner.");
return(
<p>Spinning..</p>
);
}
}
export default Spinner;
You could add a handler method to update the state from spinner
handleClick(){
this.setState({
showSpinner: true
})
}
and in your render it will need to be passed as prop
<div className="row">
{this.state.showSpinner ?
<Spinner handleClick={this.handleClick}/> :
null}
</div>
In your spinner component return you can trigger this using onclick
<button onClick = {this.props.handleClick} > Click </button>
This will allow you to update the state back in your parent, You might want to figure out how you would display the items one at a time in spinner and only set state to false when there is no items left to display.
Sorry if i misunderstood your comment.

Categories