How do I render React components dynamically using props? - javascript

I am learning React and don't quite understand how to dynamically render components based on props.
For practice, I'm building a credit card validator which works well. Once the information is valid, I want to render my component to display a thank you message. I've added a property "mode" that contains "default". My thinking is that this prop would then change to "thankYouScreen" when the credit card info is validated. When this prop changes to "thankYouScreen" it would render the ThankYouMessage component.
Is this how one would go about this?
Components
import React from 'react';
import PaymentStore from './../store/paymentStore';
class InitialPaymentScreen extends React.Component {
constructor(props) {
super(props)
}
render() {
console.log(this.props);
return (
<div className="pay-form">
<div className="pay-form-wrapper">
<div className="pay-form-title">Payment Information</div>
<form className="payment-form js-error-hook" onSubmit={this.props.store.init.bind(this.props.store)}>
<div className="payment-form-wrap payment-form-cc-name">
<label className="payment-form-label">Name on Card</label>
<input className="payment-form-input js-cc-name" maxLength="50" placeholder="Enter your name..." type="text"/>
</div>
<div className="payment-form-wrap payment-form-cc">
<label className="payment-form-label">Card Number</label>
<input className="payment-form-input js-cc-number" placeholder="1234 5678 9012 3456" type="number"/>
</div>
<div className="payment-form-wrap payment-form-exp">
<label className="payment-form-label">Expiration</label>
<input className="payment-form-input js-cc-expiration" placeholder="04/17" type="number" min="0"/>
</div>
<div className="payment-form-wrap payment-form-cvv">
<label className="payment-form-label">CVV</label>
<input className="payment-form-input js-cc-cvv" placeholder="123" type="number"/>
</div>
<input type="submit" className="payment-form-submit" onClick={this.props.store.init.bind(this.props.store)} value="Next" />
</form>
</div>
</div>
);
}
}
class ThankYouMessage extends React.Component {
constructor(props) {
super(props)
}
render() {
return(
<div>Thanks!</div>
);
}
}
class PaymentForm extends React.Component {
constructor(props) {
super(props)
}
render() {
return (
<section className="main-content payment-form-wrapper">
<InitialPaymentScreen store={this.props.route.store} mode="default"/>
</section>
);
}
}
Store
let PaymentStore = {
validateFields() {
// Validates all the information
},
displayThankYou(){
console.log("Thanks!")
// I'm assuming this is where I should update "mode" to render the component
},
};

Related

Not able to display the data stored in a state object in react

I am new to react and am trying to display the content of a json file in a component.The json
file has three data fields of a single object and it is fetched using axios into my component. The data is successfully retrieved and the state is also set(found from console.log), but when i try to display the data in the render method, it is not recognised and nothing is displayed(i.e. {this.state.lockerData.data['location']} doesn't work).
Any help is much welcome. Thanks in advance!
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import axios from 'axios';
class LockerCard extends React.Component {
constructor(props) {
super(props);
this.state = {lockerData:''}
}
componentDidMount() {
this.getLockerData();
}
getLockerData() {
axios.get('lockerDetails.json').then(response => {
this.setState({lockerData: response})
console.log(response.data);
console.log(this.state.lockerData.data['location']);
})
};
render() {
return (
<div>
<div className="grid-item">
<span id="location" >{this.state.lockerData.data['location']}</span>
<br /><br />
<b>£<span id="cost">{}</span></b>
<br/><br/>
<span id="lockeruse">{}</span>
<br/>
<input type="button" id="openButton" value="Open" />
<input type="button" id="releaseButton" value="Release" />
</div>
</div>
);
}
}
ReactDOM.render(<LockerCard />,document.getElementById('root'));
Access like this {this.state.lockerData.location}
return (
<div>
<div className="grid-item">
<span id="location" >{this.state.lockerData.location}</span>
<br /><br />
<b>£<span id="cost">{}</span></b>
<br/><br/>
<span id="lockeruse">{}</span>
<br/>
<input type="button" id="openButton" value="Open" />
<input type="button" id="releaseButton" value="Release" />
</div>
</div>
);

How to go from one page to another

I have a SignIn form and I want to create the SignUp link.
On link click I want to open SignUp page.
I have created index.js nothing in that another app.js I wrote SignIn logic.
Here is the Code :
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import './App.css';
class App extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: ""
};
}
validateForm() {
return this.state.email.length > 0 && this.state.password.length > 0;
}
handleChange = event => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = event => {
event.preventDefault();
}
render(){
return (
<div class="container">
<form onSubmit={this.handleSubmit}>
<div id="login">
<div class="form-group">
<h2 align="center">Login Form</h2>
Email :
<input type="email" id="email" value={this.state.email} onChange={this.handleChange} class="form-control" placeholder="Email Address"/><br/>
Password :
<input type="password" id="password" value={this.state.password} onChange={this.handleChange} class="form-control" placeholder="Password"/><br/>
Sign Up<br/><br/>//here I want to change
<button id="send" disabled={!this.validateForm()} class="btn btn-default">Sign In</button>
</div>
</div>
</form>
</div>
);
}
}
export default App;
I have added the Anchor tag in that but it won't work . I want to create the link in place of anchor tag in that onclick the signup page will open. I have started to create signUp page also
here is my code:
import React, { Component } from 'react';
import './App.css';
export default class Signup extends Component {
render(){
return (
<div class ="container">
<form>
<div id="signup">
<div class="form-group">
First Name :
<input type="text" id="first" class="form-control" placeholder="First Name"/><br/>
Last Name :
<input type="text" id="last" class="form-control" placeholder="Last Name"/><br/>
Email :
<input type="email" id="email" class="form-control" placeholder="Email"/><br/>
Password :
<input type="password" id="password" class="form-control" placeholder="Password"/><br/>
Re-enter Password :
<input type="password" id="confirm" class="form-control" placeholder="Confirm Password"/><br/>
<button id="save">Save</button>
</div>
</div>
</form>
</div>
);
}
}
How do I create the routes to go from one page to another?
Use Link instead of a tag:
import { Link } from 'react-router-dom';
.
.
<Link to='/signup'>Sign Up</Link>
EDIT: I'm updating the code for your solution for now, but I need you to understand you might not be getting such a solution whenever you post questions here. Stack Overflow requires you to read through any documentation and do extensive research before asking any question.
I need you to look at the code below and fully understand it by reading the React Router docs before copy-pasting it.
Change your App.js to:
import React, { Component } from 'react';
import { BrowserRouter as Router, Link, Route, Switch } from 'react-router-dom';
import Signup from './Signup';
import './App.css';
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: ""
};
}
validateForm() {
return this.state.email.length > 0 && this.state.password.length > 0;
}
handleChange = event => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = event => {
event.preventDefault();
}
render() {
return (
<div class ="container">
<form onSubmit={this.handleSubmit}>
<div id="login">
<div class="form-group">
<h2 align="center">Login Form</h2>
Email :
<input type="email" id="email" value={this.state.email} onChange={this.handleChange} class="form-control" placeholder="Email Address"/><br/>
Password :
<input type="password" id="password" value={this.state.password} onChange={this.handleChange} class="form-control" placeholder="Password"/><br/>
<Link to="/signup">Signup</Link>
<button id="send" disabled={!this.validateForm()} class="btn btn-default">Sign In</button>
</div>
</div>
</form>
</div>
)
}
}
class App extends Component {
render() {
return (
<Router>
<Switch>
<Route exact path='/' component={Login}/>
<Route path='/signup' component={Signup}/>
</Switch>
</Router>
);
}
}
export default App;
and your expected working is achieved. Let me know if that solved by accepting this answer, or comment below.
P.S: React Router docs: https://reacttraining.com/react-router/web/guides/philosophy
Happy Coding!
If you are using react-router 4.x and above, then import it like this
import {Link} from 'react-router-dom'
For react-router versions < 4.x
import {Link} from 'react-router';
And in your return, you can link to another page by
<Link to="/signup">Signup</Link>

React JS - How to rerender Independed component?

I am new to this React JS, please in this question. I Have 4 components(Insert,delete,update and show). when i insert data in Insert component then immediately it should show those details in Show components. Please find my sample code. Thanks in advance for your help.
main.js :
import React from 'react';
import ReactDOM from 'react-dom';
import Insert from './Insert.js';
import Show from './Show.js';
import Delete from './Delete.js';
import Update from './update.js';
ReactDOM.render(<Insert/>, document.getElementById('Insert'))
ReactDOM.render(<Show />, document.getElementById('Show'))
ReactDOM.render(<Delete />, document.getElementById('Delete'))
ReactDOM.render(<Update/>, document.getElementById('Update'))
My Index.html :
<table border="2" align="center">
<tr>
<td>
<h1> Insert New Record </h1>
<div id = "Insert"></div>
</td>
<td>
<h1> Show Existing Records </h1>
<div id = "Show"> </div>
</td>
</tr>
<tr>
<td>
<h1> Delete Emp Record </h1>
<div id="Delete"> </div>
</td>
<td>
<h1> Update Existing Records </h1>
<div id="update" > </div>
</td>
</tr>
<script src = "index.js"></script>
Now i need to refresh the Show component whenever i perform insert, update, delete operations.
My sample Insert Component :
import React from 'react';
import Fetch from 'react-fetch';
import Show from './show'
class Insert extends React.Component {
constructor(props) {
super(props);
this.state = {
Id:0 ,
name:'' ,
mobile: '',
email: '',
dept : '',
role :'',
child : Show
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleInputChange = this.handleInputChange.bind(this);
}
handleInputChange(event) {
const target = event.target;
const Id= target.Id;
const name = target.name;
const mobile = target.mobile;
const email = target.email;
const dept = target.dept;
const role = target.role;
this.setState({[Id]: event.target.value});
this.setState({[name]: event.target.value});
this.setState({[mobile]: event.target.value});
this.setState({[email]: event.target.value});
this.setState({[dept]: event.target.value});
this.setState({[role]: event.target.value});
}
handleSubmit(event) {
let employee={
Id:this.state.Id,
name:this.state.name,
mobile:this.state.mobile,
email:this.state.email,
dept:this.state.dept,
role:this.state.role
}
fetch('http://localhost:25424/api/Employee/CreateNewEmployee/', {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin' : 'http://localhost:7777' ,
'Access-Control-Allow-Headers' : 'Origin, X-Requested-With, Content-Type, Accept',
'Access-Control-Allow-Methods' : 'POST'
},
body: JSON.stringify(employee)
})
.then(function(resp){
})
event.preventDefault();
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label >ID</label>
<input type="number" name="Id" value={this.state.Id} onChange={this.handleInputChange} />
<br/>
<label >name</label>
<input type="text" name="name" value={this.state.name} onChange={this.handleInputChange} />
<br/>
<label >Mobile</label>
<input type="text" name="mobile" value={this.state.mobile} onChange={this.handleInputChange} />
<br/>
<label >Email</label>
<input type="text" name="email" value={this.state.email} onChange={this.handleInputChange} />
<br/>
<label >Dept</label>
<input type="text" name="dept" value={this.state.dept} onChange={this.handleInputChange} />
<br/>
<label >Role</label>
<input type="text" name="role" value={this.state.role} onChange={this.handleInputChange} />
<br/>
<input type="submit" value="Submit" />
</form>
);
}
}
export default Insert;
This is the file structure you need to aim for in a React app
- src/
- components/
- insert.js
- delete.js
- update.js
- show.js
- main.js
- index.html
for example:
main.js // should contain all the data(state) and should flow downwards to your child components
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import 'insert' from /route/to/insert.js
import 'delete' from /route/to/delete.js
import 'show' from /route/to/show.js
import 'update' from /route/to/update.js
class Main extends Component {
constructor(props) {
super(props);
this.state = {//initialize state object}
}
render() {
return ( //jsx
<table border="2" align="center">
<tr>
<(insert.js component)/>
<(delete.js component)/>
</tr>
<tr>
<(update.js component)/>
<(show.js component)/>
</tr>
)
}
}
ReactDOM.reder(<Main/>, document.querySelector('one DOM element'))
and then... make each separate components to render out JSX into the main.js
Hope that makes sense :/
You dont have a parent child relationship in between you components. You will need all of this in one parent React component, lets say Main.jsx.
and it should look something like this:
Main.jsx:
import React from 'react';
class Main extends React.Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.state = {
flag: 0,
}
handleSubmit(){
this.setState({flag : this.state.flag});
}
render() {
return(<div>
<Insert handleSubmit = {this.handleSubmit}/>
<Show/>
<Delete/>
<Update />
</div>);
}
}
export default Main
You can put the structure of DOM or layout as per your desire in render. In handleSubmit function m reassigning the same state again so that it can re render. You can also use this.forceUpdate() for this but it is not advisable in some cases.
Your handleSubmit function in Insert Component would look need to call the props function as this.props.handleSubmit() so that it can re render the main component which in turn will re render your show update and delete.
Hope it helps.

how to display the table using react js

Im new to reactjs and Im just trying to create a page with the userName and password. When the submit is clicked it should display a list of table names in the same page. For this I have two react components, placed it in a separate js file. So when the button is clicked the table names should be generated. I have tried a sample code but I'm unable to display the list. So looking for help in reactjs.
tableContent.js
import React from 'react';
class tableContent extends React.Component {
render() {
return (
<select name="sometext" multiple="multiple">
<option>Table1</option>
<option>Table2</option>
<option>Table3</option>
<option>Table4</option>
<option>Table5</option>
</select>
)
}
}
export default tableContent;
login.js
import React from 'react';
import tableContent from './tables';
class Login extends React.Component{
constructor(){
super();
this.state={
showComponent : false,
};
this.buttonClick = this.buttonClick.bind(this);
}
buttonClick(){
this.setState({
showComponent: true,
})
}
render(){
return(
<div>
<form>
<label>userName :</label>
<input type="text" />
<br/>
<label>Password :</label>
<input type="text" />
<button onClick={this.buttonClick.bind(this)}> Submit </button>
</form>
<tableContent />
</div>
)
}
}
export default Login;
Change the Name tableContent to TableContent, because name of the react component must start will upper case letter otherwise it will be treated as html element.
Use e.preventDefault(); inside buttonClick function to prevent the form submission automatically.
Check the working code:
class Login extends React.Component{
constructor(){
super();
this.state={
showComponent : false,
};
}
buttonClick(e){
e.preventDefault();
this.setState({
showComponent: true,
})
}
render(){
return(
<div>
<form>
<label>userName :</label>
<input type="text" />
<br/>
<label>Password :</label>
<input type="text" />
<button onClick={this.buttonClick.bind(this)}> Submit </button>
</form>
{this.state.showComponent && <TableContent />}
</div>
)
}
}
class TableContent extends React.Component {
render() {
return (
<select name="sometext" multiple="multiple">
<option>Table1</option>
<option>Table2</option>
<option>Table3</option>
<option>Table4</option>
<option>Table5</option>
</select>
)
}
}
ReactDOM.render(<Login/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id ='app'/>

Getting data from child select box in parent using ReactJS

I have a child component with a select form element, this queries my API and makes a select box out of the data. I then try to pass the option back that's been selected via an OnChange function to my parent component so I can then send my data back to the server. I keep getting an error saying state is not defined, I am new to react and can't see where I am going wrong.
Here is my parent component
var ReactDom = require('react-dom');
const uuid = require('uuid/v1');
import {postDataTest} from "../actions/postData";
import TeamSelectBox from "./TeamSelectBox";
import React, {Component, PropTypes} from "react";
class PlayerForm extends Component {
constructor(props) {
super(props);
this.state = {
teamId: ''
};
this.handleChange = this.handleChange.bind(this);
}
fieldValues = {
name: null,
teamName: null,
bio: null
}
handleChange(dataFromChild) {
console.log(dataFromChild);
}
nextStep(e) {
e.preventDefault();
// Get values via this.refs
var player = {
id: uuid(),
name: ReactDom.findDOMNode(this.refs.name).value,
teamName: ReactDom.findDOMNode(this.refs.teamName).value,
bio: ReactDom.findDOMNode(this.refs.bio).value,
teamId: ReactDom.findDOMNode(this.refs.teamId).value
};
postDataTest(player);
}
render() {
return (
<div className="row">
<div className="col-md-6">
<div className="panel">
<div className="panel-heading">
<h1>Add Player</h1>
</div>
<div className="panel-body">
<form className="form-horizontal">
<div className="form-group">
<label className="control-label">Name</label>
<input type="text" className="form-control" ref="name" defaultValue={this.fieldValues.name}/>
</div>
<div className="form-group">
<label className="control-label">Team Name</label>
<input type="text" className="form-control" ref="teamName" defaultValue={this.fieldValues.teamName}/>
</div>
<TeamSelectBox state={this.state.teamId} onChange={this.handleChange}/>
<div className="form-group">
<label className="control-label">Bio</label>
<input type="textarea" className="form-control" ref="bio" defaultValue={this.fieldValues.bio}/>
</div>
<div className="bs-component">
<button className="btn btn-md btn-default btn-block" onClick={this.nextStep}>Save & Continue</button>
</div>
</form>
</div>
</div>
</div>
</div>
)
}
}
module.exports = PlayerForm;
And here is my child form select box
import React, {Component} from "react";
import axios from "axios";
import {postDataTest} from '../actions/postData';
class TeamSelectBox extends Component {
constructor(props) {
super(props);
this.state = {
teams: []
};
}
componentDidMount() {
axios.get("/api/teams")
.then(response => {
const teams = response.data;
this.setState({teams});
console.log(teams);
});
}
render() {
return (
<div className="form-group">
<label for="inputSelect" className="control-label">Select Team</label>
<div className="bs-component">
<select value={this.probs.state.teamId} onChange={this.probs.onChange} className="form-control">
<option value=""></option>
{this.state.teams.map(singleTeam =>
<option value={singleTeam.id}>{singleTeam.team.name}</option>
)}
</select>
</div>
</div>
);
}
}
export default TeamSelectBox;
Your approach seems OK, but you had a typo in your child Component:
{this.probs.onChange}
change it to {this.props.onChange} and try again!
i think you have a typo, you missed spell props, this.props not this.probs

Categories