I need to pass a URL from a class component to another - reactjs

here is my QR component :
import React, { Component } from "react";
class QR extends React.Component {
constructor(props) {
super(props);
}
render() {
const { catImageUrl } = this.props;
const qrUrl = `https://qrtag.net/api/qr_12.svg?url=${catImageUrl}`;
if (!catImageUrl) return <p>Oops, something went wrong!</p>;
return <img className="QR" src={qrUrl} alt="qrtag" />;
}
}
export default QR;
I need to pass the const qrURL to the next component Form.js to use it in ajax call to get its data and pass it to the next api request to send it to an email
class Form extends React.Component{
constructor(props) {
super(props);
this.state = {
name: '',
email: '',
message: '',
}
}
const{qrUrl}=this.props;
FetchQRURL = () => {
fetch(`${qrUrl}`)
.then((response) => response.json())
.then((data) => {
this.setState({
message: data,
});
})
.catch((error) => console.log(error));
};
handleSubmit(e){
e.preventDefault();
axios({
method: "POST",
url:"http://localhost:3002/send",
data: this.state
}).then((response)=>{
if (response.data.status === 'success'){
alert("Message Sent.");
this.resetForm()
}else if(response.data.status === 'fail'){
alert("Message failed to send.")
}
})
}
resetForm(){
this.setState({name: '', email: '', message: ''})
}
render() {
return(
<div className="App">
<form id="contact-form" onSubmit={this.handleSubmit.bind(this)} method="POST">
<div className="form-group">
<label htmlFor="name">Name</label>
<input type="text" className="form-control" id="name" value={this.state.name} onChange={this.onNameChange.bind(this)} />
</div>
<div className="form-group">
<label htmlFor="exampleInputEmail1">Email address</label>
<input type="email" className="form-control" id="email" aria-describedby="emailHelp" value={this.state.email} onChange={this.onEmailChange.bind(this)} />
</div>
<div className="form-group">
<label htmlFor="message">Message</label>
<textarea className="form-control" rows="5" id="message" value={this.state.message} onChange={this.onMessageChange.bind(this)} />
</div>
<button type="submit" className="btn btn-primary" onClick="">Submit</button>
</form>
</div>
);
}
onNameChange(event) {
this.setState({name: event.target.value})
}
onEmailChange(event) {
this.setState({email: event.target.value})
}
onMessageChange(event) {
this.setState({message: event.target.value})
}
}
export default Form;
you can see I tried to pass it as props but it doesn't work
here I tried to pass it as props(in my app.js)
import React, { Component } from "react";
import RandomCat from "./RandomCat.js";
import QR from "./QR.js";
import Form from "./form.js";
class BooksApp extends Component {
state = {
showCatImage: false,
showQrCode: false,
catImageUrl: "",
};
handleFetchRandomImage = () => {
fetch("https://aws.random.cat/meow")
.then((response) => response.json())
.then((data) => {
this.setState({
catImageUrl: data.file,
showCatImage: true,
});
})
.catch((error) => console.log(error));
};
handleShowQrCode = () => {
this.setState({ showQrCode: true });
};
render() {
const { showCatImage, showQrCode, catImageUrl,qrUrl } = this.state;
return (
<div className="app">
<div className="first">
{/* The time below shows cat image if showCatImage === true and returns nothing if false */}
{showCatImage && <RandomCat catImageUrl={catImageUrl} />}
<button className="catButton" onClick={this.handleFetchRandomImage}>
Generate Cat
</button>
</div>
<div className="second">
{showQrCode && <QR catImageUrl={catImageUrl} qrUrl={qrUrl}/>}
<button className="QRButton" onClick={this.handleShowQrCode}>
Geanerate QR
</button>
</div>
<div>
<Form qrUrl={qrUrl}/>
</div>
</div>
);
}
}
export default BooksApp;
any idea how can I pass it to the Form.js?

You have to pull the constant qrUrl to the parent component which is BooksApp in your case.
Set it to the state and pass it down as props.
state = {
showCatImage: false,
showQrCode: false,
catImageUrl: "",
qrUrl: ""
};
handleFetchRandomImage = () => {
fetch("https://aws.random.cat/meow")
.then((response) => response.json())
.then((data) => {
this.setState({
catImageUrl: data.file,
showCatImage: true,
qrUrl: `https://qrtag.net/api/qr_12.svg?url=${data.file}` // Set it here
});
})
.catch((error) => console.log(error));
};
handleShowQrCode = () => {
this.setState({ showQrCode: true });
};
render() {
const { showCatImage, showQrCode, catImageUrl, qrUrl } = this.state;
return (
<div className="app">
<div className="first">
{/* The time below shows cat image if showCatImage === true and returns nothing if false */}
{showCatImage && <RandomCat catImageUrl={catImageUrl} />}
<button className="catButton" onClick={this.handleFetchRandomImage}>
Generate Cat
</button>
</div>
<div className="second">
{showQrCode && <QR catImageUrl={catImageUrl} qrUrl={qrUrl}/>}
<button className="QRButton" onClick={this.handleShowQrCode}>
Geanerate QR
</button>
</div>
<div>
<Form qrUrl={qrUrl}/>
</div>
</div>
);
}
}
export default BooksApp;
The just use it with this.props.qrUrl in your other components.

Related

How Can I get first element from API array

I am learning React and API. Here I am fetching data from API.I am trying to do on click button one user should appear. Or on click of user name all other user info should appear. I want to display one element from API array.If click on button new user should show. How to get only one user or one user info. Botton I added input box which can shoe only one value. I am stuck here.
import React from 'react';
import './App.css';
class Home extends React.Component {
constructor(props) {
super(props)
this.state = {
items: [],
error: '',
email:'',
phone:'',
companyName:''
}
this.handleInputChange = this.handleInputChange.bind(this);
this.showUserEmail = this.showUserEmail.bind(this);
}
handleInputChange(event){
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSelectUserName = (event) => {
console.log(event.target.value);
const myUser = (event.target.value);
this.setState({ name: event.target.value });
const selectedUser= event.target.value;
}
showUserEmail=(e)=>{
console.log("you are clicking name" );
this.setState({
})
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((result) => {
console.log(result);
console.warn(result);
this.setState({ items: result });
});
}
render() {
const { items } = this.state
return (
<div>
<button className="btn"> Show new User</button>
<div className="new-user" onChange={event => this. handleSelectNewUser(event)}>
{this.state.items.map(items => (
<span key={items.name} value={items.name}>
{items.name} <p></p></span>))}
</div>
<p className="para-text"> Data from API</p>
<div className="user-info">
{
items.length ?
items.map(items => <div key ={ items.id }>
<div className="user-details"> {items.name} </div>
<div className="user-details">{items.phone}</div>
<div className="user-details">{items.company.name}</div>
<div className="user-details">{items.username}</div>
<div className="user-details">{items.email}</div>
<div className="user-details">{items.website}</div>
</div>) : null
}
</div>
<h2>Find User By Username</h2>
<div className="input-box">
<select onChange={event => this.handleSelectUserName(event)}>
{this.state.items.map(items => (
<option key={items.name} value={items.name}>
{items.username}
</option>
))}
</select>
{/* Auto select */}
<div className=" Show-User-Auto">
<div className="input-box">
<input type="text"
placeholder=" Auto Select"
required="required"
onChange={event => this.handleInputChange(event)}
value={this.state.name} />
</div>
</div>
</div>
</div>
);
}
}
export default Home;
You have to maintain a state which contains userId , then you can condition render it like below code
import React from "react";
class Users extends React.Component {
constructor(props) {
super(props);
this.state = {
items: [],
error: "",
email: "",
phone: "",
companyName: "",
userId: "",
orgList: []
};
this.handleInputChange = this.handleInputChange.bind(this);
this.showUserEmail = this.showUserEmail.bind(this);
}
handleSetUserId = (userId) => {
if (userId === this.state.userId) {
this.setState({ userId: "" });
} else {
this.setState({ userId });
}
};
handleInputChange(event) {
const target = event.target;
const value = target.type === "checkbox" ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
handleSelectUserName = (event) => {
console.log(event.target.value);
const myUserId = event.target.value;
if (myUserId) {
console.log(this.state.orgList, "this.state.orgList");
let selectedUser = this.state.orgList.filter((item) => {
return item.id == Number(myUserId);
});
console.log(selectedUser, "selectedUser");
this.setState({ items: selectedUser });
}
};
showUserEmail = (e) => {
console.log("you are clicking name");
this.setState({});
};
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/users")
.then((res) => res.json())
.then((result) => {
console.log(result);
console.warn(result);
this.setState({ items: result, orgList: result });
});
}
handleFetchAllUsers=()=>{
this.setState({items:this.state.orgList})
}
render() {
const { items } = this.state;
return (
<div>
<button className="btn" onClick={()=>this.handleFetchAllUsers()}> Show All User</button>
<div
className="new-user"
onChange={(event) => this.handleSelectNewUser(event)}
>
{this.state.items.map((items) => (
<span key={items.name}>
<br />
<span onClick={() => this.handleSetUserId(items.id)}>
{items.name}
<br />
</span>
{items.id === this.state.userId && (
<p>
<br />
<div className="user-details">{items.phone}</div>
<div className="user-details">{items.company.name}</div>
<div className="user-details">{items.username}</div>
<div className="user-details">{items.email}</div>
<div className="user-details">{items.website}</div>
</p>
)}
</span>
))}
</div>
<p className="para-text"> Data from API</p>
<h2>Find User By Username</h2>
<div className="input-box">
<select onChange={(event) => this.handleSelectUserName(event)}>
{this.state.orgList.map((items) => (
<option key={items.name} value={items.id}>
{items.username}
</option>
))}
</select>
{/* Auto select */}
<div className=" Show-User-Auto">
<div className="input-box">
<input
type="text"
placeholder=" Auto Select"
required="required"
onChange={(event) => this.handleInputChange(event)}
value={this.state.name}
/>
</div>
</div>
</div>
</div>
);
}
}
export default Users;
I have implemented the same in codesandbox you can use for ref

React form submit triggers two times

I have React login form. The problem is form submit is called two times. I dont understand it. Can somebody tell me please why? Thanks a lot.
import React from "react"
import LoginErrors from "./LoginErrors"
import LoginSuccess from "./LoginSuccess"
import axios from 'axios'
import { withRouter } from "react-router-dom";
class Login extends React.Component
{
constructor(props)
{
super(props)
this.state = {
name: '',
password: '',
errors: [],
success: []
}
}
changeName = e =>
{
this.setState({name: e.target.value});
}
changePassword = e =>
{
this.setState({password: e.target.value});
}
sendData(e)
{
e.preventDefault();
this.setState({'errors': [], 'success': []});
let formData = new FormData();
formData.set('name', this.state.name);
formData.set('password', this.state.password);
axios({
method: 'POST',
url: 'http://localhost:8000/login',
data: formData,
headers: {
'Content-Type': 'text/html',
'X-Requested-With': 'XMLHttpRequest',
}
})
.then(response => {
// ? returns undefined if variable is undefined
if( response.data?.errors?.length )
{
this.setState({errors: response.data.errors})
}
if( response.data?.success?.length )
{
let data = response.data
this.props.setAccessToken(data.token)
this.props.setUserName(data.user.name)
this.props.history.push('/')
}
})
.catch(response => {
this.setState({errors: ['Login fails. Try it again later please.']})
});
}
render() {
return (
<div className="row justify-content-md-center">
<div className="col-sm-12 col-md-6">
<div id="loginForm">
<h2 className="">Login</h2>
<LoginSuccess success={this.state.success} />
<LoginErrors errors={this.state.errors} sendParentMessage={this.handleErrorsChildMessage} />
<form onSubmit={e => {this.sendData(e)}}>
<div className="form-group">
<label htmlFor="name">Name</label>
<input ref={this.email} name="name" className="form-control" type="text" onChange={this.changeName} />
</div>
<div className="form-group">
<label htmlFor="password">Heslo</label>
<input ref={this.password} name="password" className="form-control" type="password" onChange={this.changePassword} />
</div>
<div className="form-group">
<button name="sbmt" className="btn btn-primary" type="submit">OdoslaƄ</button>
</div>
</form>
</div>
</div>
</div>
);
}
}
So the problem is in axios preflyght request which is related to the CORS policy. But How to stop it?

Redirection to dashboard after login in react

I have a login page, and I want to redirect users to dashboard after the details are filled.
I have tried using history.push and redirect components but I couldn't redirect.
Login Page
class Login extends React.Component {
state = {
email: '',
password: '',
errors: {},
redirect: false
}
validateForm = () => {
let errors = {};
let formIsValid = true;
if(!this.state.email) {
formIsValid = false;
errors['email'] = 'Please enter email to continue';
}
if(!this.state.password) {
formIsValid = false;
errors['password'] = 'Please enter password to continue';
}
this.setState({
errors: errors
})
return formIsValid;
}
handleChange = (event) => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = (event) => {
event.preventDefault();
// console.log(this.state);
if(this.validateForm()) {
const loginData = {
email: this.state.email,
password: this.state.password
}
axios
.post('/users.json', loginData)
.then(response => {
console.log(response.data);
})
.catch(error => {
console.log(error);
})
}
}
render() {
return (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">Login</h5>
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={this.handleChange} />
<p>{this.state.errors.email}</p>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={this.handleChange} />
<p>{this.state.errors.password}</p>
</div>
<div className="input-field">
<button onClick={this.redirectHandler} className="btn btn-primary">Login</button>
</div>
</form>
</div>
)
}
}
export default Login;
I want to redirect to other page once the form is submitted with the email and password.
I've been trying this for days but I couldn't find a solution.
import { withRouter } from 'react-router';
class Login extends React.Component {
state = {
email: '',
password: '',
errors: {},
redirect: false
}
validateForm = () => {
let errors = {};
let formIsValid = true;
if(!this.state.email) {
formIsValid = false;
errors['email'] = 'Please enter email to continue';
}
if(!this.state.password) {
formIsValid = false;
errors['password'] = 'Please enter password to continue';
}
this.setState({
errors: errors
})
return formIsValid;
}
handleChange = (event) => {
this.setState({
[event.target.id]: event.target.value
});
}
handleSubmit = (event) => {
event.preventDefault();
// console.log(this.state);
if(this.validateForm()) {
const loginData = {
email: this.state.email,
password: this.state.password
}
axios
.post('/users.json', loginData)
.then(response => {
this.props.history.push("/dashboard");
console.log(response.data);
})
.catch(error => {
console.log(error);
})
}
}
render() {
return (
<div className="container">
<form onSubmit={this.handleSubmit} className="white">
<h5 className="grey-text text-darken-3">Login</h5>
<div className="input-field">
<label htmlFor="email">Email</label>
<input type="email" id="email" onChange={this.handleChange} />
<p>{this.state.errors.email}</p>
</div>
<div className="input-field">
<label htmlFor="password">Password</label>
<input type="password" id="password" onChange={this.handleChange} />
<p>{this.state.errors.password}</p>
</div>
<div className="input-field">
<button onClick={this.redirectHandler} className="btn btn-primary">Login</button>
</div>
</form>
</div>
)
}
}
export default withRouter(Login);
have some complain about your code.
first: for form validation and handling you dont need to use state,
there is a library called Formik which will help you a lot with
this.
second: if you are using redux to check user is logged in or
not you need to create a private route for routes which cannot be
accessible for public like here dashboard component.
third: to use history you need to wrap your
component inside withRouter HOC which will pass route props to your
component so you can use history or if your are using functional component you can use useHistory() hook.

Grabbing React form field values for submission

Given a React form, I'm having trouble getting the value from the selected radio button, and text box if other is selected. I should be able to pass the fields into the send() for the post, but not sure how to grab them.
class CancelSurvey extends React.Component {
constructor (props) {
super(props)
this.state = {
reasons: [],
reason: {}
}
this.processData = this.processData.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
this.otherSelected = this.state.reason === "otheroption";
}
componentDidMount () {
this.fetchContent(this.processData)
}
/**
* Fetch reasons
*/
fetchContent (cb) {
superagent
.get('/api/user/survey')
.then(cb)
}
/**
* Set state after reasons have been fetched
* #param data
*/
processData (data) {
this.setState({
reasons: data.body
})
}
handleSubmit (e) {
e.preventDefault()
let reason = this.state.reason
if (reason === 'otheroption') {
reason = this.state.otherreason
}
console.log(reason)
superagent
.post('/api/user/survey')
.send({
optionId: this.state.reason.reason_id,
optionText: this.state.reason.client_reason,
otherReasonText: this.state.otherreason
})
.then(function (res) {
console.log('Survey Sent!')
})
}
/**
* render
*/
render (props) {
const content = this.props.config.contentStrings
const reason = this.state.reasons.map((reason, i) => {
return (
<div className='fieldset__item' key={i}>
<label>{reason.client_reason}</label>
<input type='radio'
id={reason.reason_id}
value={reason.client_reason}
name='reason'
checked={this.state.reason.reason_id === reason.reason_id}
onChange={() => this.setState({reason})} />
</div>
)
})
return (
<div className='survey'>
<h2 className='heading md'>{content.memberCancel.exitSurvey.heading}</h2>
<p className='subpara'>{content.memberCancel.exitSurvey.subHeading}</p>
<form id='exit-survey' onSubmit={this.handleSubmit}>
<fieldset className='fieldset'>
{ reason }
<label>Other reason not included above:</label>
<input type='radio'
id='otheroption'
name='reason'
value={this.state.reason.otherreason}
onChange={() => this.setState({reason:{reason_id: 70, client_reason: 'other'}})} />
<input className='valid'
type='text'
id='otheroption'
name='othertext'
placeholder={content.memberCancel.exitSurvey.reasonPlaceholder}
onChange={(event) => this.setState({otherreason: event.target.value})} />
</fieldset>
<div className='footer-links'>
<button className='btn btn--primary btn--lg' onClick={this.handleSubmit}>{content.memberCancel.exitSurvey.button}</button>
</div>
</form>
</div>
)
}
}
export default CancelSurvey
Your variables aren't correct. I've update them to what I think is correct.
handleSubmit (e) {
e.preventDefault()
superagent
.post('/api/user/survey')
.send({
optionId: this.state.reason.reason_id,
optionText: this.state.reason.client_reason,
otherReasonText: this.state.reason.otherreason
})
.then(function (res) {
console.log('Survey Sent!')
})
.catch(function (err) {
console.log('Survey submission went wrong...')
})
}
/**
* render
*/
render (props) {
const content = this.props.config.contentStrings
const reason = this.state.reasons.map((reason, i) => {
return (
<div className='fieldset__item' key={i}>
<label>{reason.client_reason}</label>
<input
type='radio'
id={reason.reason_id}
name='reason'
checked={this.state.reason.reason_id === reason.reason_id}
value={reason.client_reason}
onChange={() => this.setState({reason})} />
</div>
)
})
return (
<div className='survey'>
<h2 className='heading md'>{content.memberCancel.exitSurvey.heading}</h2>
<p className='subpara'>{content.memberCancel.exitSurvey.subHeading}</p>
<form id='exit-survey' onSubmit={this.handleSubmit}>
<fieldset className='fieldset'>
{ reason }
<label>Other reason not included above:</label>
<input type='radio'
id='otheroption'
name='otheroption'
value={this.state.reason.otherreason}
checked={this.state.reason.reason_id === 0}
onChange={() => this.setState({ reason: {reason_id: 0, client_reason: ""} })} />
<input className='valid'
type='text'
id='othertext'
name='othertext'
value={this.state.reason.otherreason}
placeholder={content.memberCancel.exitSurvey.reasonPlaceholder}
onChange={(event) => this.setState({ reason: {reason_id: 0, client_reason: "", otherreason: event.target.value} })} />
</fieldset>
<div className='footer-links'>
<button className='btn btn--primary btn--lg' onClick={this.handleSubmit}>{content.memberCancel.exitSurvey.button}</button>
</div>
</form>
</div>
);
}

Event / callback for when a user logs in with Meteor + React?

Im using Meteor and React. I need to redirect a user when they log in. Is there an event or callback for this?
import React from 'react';
import { Link, Redirect } from 'react-router-dom';
import './LogInPage.less';
class LogIn extends React.Component {
constructor(props) {
super(props);
this.state = {
error: false,
loggedIn: Meteor.userId() ? true : false,
};
this.login = this.login.bind(this);
}
login = e => {
e.preventDefault();
Meteor.loginWithPassword(this.email.value, this.password.value, err => {
if (err) {
this.setState({ error: err.reason });
}
});
// if (Meteor.userId()) this.setState({ loggedIn: true });
};
render() {
// if (Meteor.userId()) return <Redirect to="/" />;
return (
<div className="LogIn">
<form onSubmit={this.login}>
<label>Email</label>
<input type="email" ref={input => (this.email =
<label>Password</label>
<input type="password" ref={input => (this.password = input)} />
<button className="btn" type="submit">
Log in
</button>
{this.state.error && (
<p className="form-std__msg form-std__msg--err">
{this.state.error}
</p>
)}
</form>
</div>
);
}
}
export default LogInPage;
If no error then you can check using Meteor.user()
import React from 'react';
import { Link, Redirect } from 'react-router-dom';
import './LogInPage.less';
class LogIn extends React.Component {
constructor(props) {
super(props);
this.state = {
error: false,
loggedIn: Meteor.userId() ? true : false,
};
this.login = this.login.bind(this);
}
login = e => {
e.preventDefault();
Meteor.loginWithPassword(this.email.value, this.password.value, err => {
if (err) {
this.setState({ error: err.reason });
} else {
this.setState({ loggedIn: Meteor.user() ? true : false })
}
});
// if (Meteor.userId()) this.setState({ loggedIn: true });
};
render() {
if (this.state.loggedIn) return <Redirect to="/" />;
return (
<div className="LogIn">
<form onSubmit={this.login}>
<label>Email</label>
<input type="email" ref={input => (this.email = input)} />
<label>Password</label>
<input type="password" ref={input => (this.password = input)} />
<button className="btn" type="submit">
Log in
</button>
{this.state.error && (
<p className="form-std__msg form-std__msg--err">
{this.state.error}
</p>
)}
</form>
</div>
);
}
}
export default LogInPage;

Resources