Having Difficulty sending state data on form to different component - reactjs

I understand that this question has been asked many different times. I've looked through many different ones and I'm still having a difficult time understanding it.
I've read many articles online and I know that I need to pass my state to props and I'm having a difficult time doing so. I managed to pass a simple string of test, however I cannot pass my state to props as it simply returns nothing and I'm not sure why if the values on the form get updated in the onchange method.
I also want to avoid using redux as a alternative as I'm trying to learn the basic way first
What I'm trying to do is very simple, user fills out a box that contains ordernumber on the form. They hit submit, redirects to another page where I'll have access to the ordernum they submitted on the input box for the order number.
Here is my code:
simple input form page
/*eslint-disable no-unused-vars*/
import React from 'react';
import ReactDOM from 'react-dom';
class Reloform extends React.Component {
constructor(props){
super(props);
this.state = {
orderNum: "",
errorMsg: ""
}
}
onChange(e){
this.setState({
[e.target.name]: e.target.value
})
}
onSubmit(e){
if(this.state.orderNum === '') {
this.setState({
errorMsg: 'Please enter your order number.'
});
} else {
this.setState({
errorMsg: ''
});
// Submission successful
window.location = '/relotoForm';
}
e.preventDefault();
}
render() {
console.log(this.props)
return (
<div className="container">
// I get message prop back but not orderNum?
<h1>{this.props.message}</h1>
<h1>{this.props.orderNum}</h1>
<div className="reloContainer">
<form
method="POST"
id="reloForm"
onSubmit={e => this.onSubmit(e)}
autoComplete="off"
>
<h1>T/O Form</h1>
{this.state.errorMsg !== '' ? <p style={{color:'#E2231A'}}>Please enter an order number.</p> : ''}
<label>Order #</label>
<input
type="text"
name="orderNum"
className="form-control"
value={this.state.orderNum}
onChange={e => this.onChange(e)}
/>
<button type="submit" className="btn btn primary" id="reloButton" onClick={this.props.updateData}>Submit</button>
</form>
</div>
</div>
)
}
}
export default Reloform;
/* form action page */
/*eslint-disable no-unused-vars*/
import React from 'react';
import ReactDOM from 'react-dom';
import Reloform from './reloForm';
class Relotoform extends React.Component {
render() {
return (
<div>
//The string that I returned works but the state that I try to have access on this page does not. I am not sure why. My assumption is because maybe this.state is referring to the state of this component and not the form component on my form page?
<Reloform message="Works" orderNum={this.state.orderNum} />
</div>
)
}
}
export default Relotoform;

State is local to the component you are accessing. If you want to pass a state value to another component, this is where you use props. So when you are trying to render Reloform in your Relotoform component, when you do orderNum={this.state.orderNum}, you won't get any value as there is no state defined for Relotoform in which there's a variable called orderNum.
You need to update the orderNum through your state in the Reloform. You get message displayed because you are passing the value "Works" as a prop in Relotoform. Then you are accessing it correctly as a prop in Reloform. Adapt a similar arhcitecture for orderNum.

Related

React.js Controlled Input in child component

I am trying to have a controlled input set up in a child component (the Search component). I wanted to keep the input state in the main App component so that I can access it in my apiCall method. I am getting the following error:
Warning: You provided a value prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultValue. Otherwise, set either onChange or readOnly.
However, I did add an onChange handler. I'm assuming the problem is that the onChange handler function is in the parent component and React doesn't like this. I did try moving the input to the main App component and worked fine (logged input to console).
Am I going about this wrong? And is there a way to set it up so that I can access the input from the Search component in the App component? I was hoping to keep most of my code/functions/state in the main App component.
Here is the App component
import React, { Component } from "react";
import './App.css';
import Header from './Components/Header'
import Search from './Components/Search'
import MainInfo from './Components/MainInfo'
import Details from './Components/Details'
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
weather: null,
main: '',
wind: '',
loading: null,
cityInput: 'Houston',
city: 'City Name',
date: new Date()
};
this.apiCall = this.apiCall.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleChange(event) {
this.setState({
cityInput: event.target.value
})
console.log(this.state.cityInput)
}
// Fetch data from OpenWeatherAPI
apiCall() {
this.setState({
loading: true
})
const currentWeather = fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${this.state.cityInput}&appid={apiKey}&units=imperial`
).then((res) => res.json());
const futureWeather = fetch(
`https://api.openweathermap.org/data/2.5/forecast?q=houston&appid={apiKey}&units=imperial`
).then((res) => res.json());
const allData = Promise.all([currentWeather, futureWeather]);
// attach then() handler to the allData Promise
allData.then((res) => {
this.setState({
weather: res[0].weather,
main: res[0].main,
wind: res[0].wind,
city: res[0].name
})
});
}
componentDidMount() {
this.apiCall();
}
render() {
return (
<div className="container-fluid bg-primary vh-100 vw-100 d-flex flex-column align-items-center justify-content-around p-3">
<Header />
<Search cityInput={this.state.cityInput} />
<MainInfo main={this.state.main} date={this.state.date} city={this.state.city} weather={this.state.weather} />
<Details main={this.state.main} wind={this.state.wind} />
</div>
);
}
}
export default App;
Here is Search component
import React, { Component } from "react";
class Search extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="row">
<div className="col-12">
<div className="d-flex">
<input className="form-control shadow-none mx-1" placeholder="Enter a city..." value={this.props.cityInput} onChange={this.handleChange}></input>
<button className="btn btn-light shadow-none mx-1" onClick={this.apiCall}>Test</button></div>
</div>
</div>
);
}
}
export default Search;
The Search component is indeed unaware of the implementation of the onChange function you have made in your App. If you really want to use a function from the parent (App) component in the child (Search), you'll need to add it as a property, as such:
<Search cityInput={this.state.cityInput} onChange={this.onChange} />
Then, you need to set it in the Child component's constructor:
constructor(props) {
super(props);
this.onChange = props.onChange;
}
I also suggest you'll have a look at React's functional approach with hooks https://reactjs.org/docs/hooks-intro.html, which makes all this a whole lot less fiddly, in my opinion. But it might take a bit to get used to.
u can pass functions like ur handler over the prop to childrens and update so from a child to the mother of the children, in the children u give the value the prop u supply from mother
<Select dataFeld="broker" id="yourid" value={this.state.brokerSel} ownonChange={(e) => this.setState({statename: e})

Directing to a new route on the basis of response from server in React

I am working in a user authentication project using react-express server . I created a server which sends a confirmation code to the user for creating a new account.However that's not the case if the user enters an email which is already used .So I need to redirect to a new route on the basis of the response of from the server.How should I go from here ownward.
import axios from 'axios';
import React, { Component } from 'react'
import'./reset.css'
export default class reset extends Component {
constructor(){
super();
this.state={
Email:'',
Response:''
}
this.handleClick = this.handleClick.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleClick(e){
this.setState({
[e.target.name]:e.target.value
})
}
handleSubmit(e){
e.preventDefault();
axios.post('http://localhost:5000/resetPassword',{
Email:this.state.Email
}).then((res)=>{
if(res.data ==`An email has been sent to ${this.state.Email}`){
<redirect to ='/home'/>
}
else{
this.setState({
Email:'',
Response:res.data
})
}
})
}
render() {
return (
<div>
<div className="Container">
<div className="subContainer">
<div className="message">{this.state.Response}</div>
<p className="notice">Enter your email to reset the password</p>
<form className="form">
<input className="takeEmail" type = "email" name="Email" onChange={this.handleClick} value={this.state.Email}placeholder="Enter your email" required/>
<button type="button" onClick={this.handleSubmit}>Submit</button>
</form>
</div>
</div>
</div>
)
}
}
I just want to redirect to a new route where a user can enter the confirmation code . I simply want a automatic redirection if certain response is obtained.
If I understood your question correctly. to redirect using react-router in javascript parts of code, you should use history object that is in the route component's props (if your component is not connected to Router directly, you can use withRouter HOC) instead of using <Redirect /> component (it is JSX and only related to render part).
like: this.props.history.push('/route_name', { Email, Response })
you are also checking email message using double equals. you should change it to === (triple equals). also, try to find a better approach to finding out if the request was successful or not.

Get value from input component and use it in another component in React

I'm new to React and have this simple code example where I simply need to take value from input and show the value back.
class App extends React.Component {
constructor(props){
super(props);
this.state = { word : ""};
this.onClick = this.onClick.bind(this);
}
onClick(e){
this.setState({word : /* how to obtain input value?? */});
}
render() {
return (
<>
<form>
<input type="text"/>
<button onClick={this.onClick}>Say it!</button>
</form>
<div>
{this.state.word}
</div>
</>
);
}
}
I know react want's me to use component state as a way to propagate information from parent component to it's children. What I don't know is how I should obtain state of a children to be used in another children.
I believe this should be doable in react in simple manner as the equivalent way of doing it using pure DOM or JQuery would also be very simple (one or two lines of code).
You can use createRef
import React, { createRef } from "react";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { word: "" };
this.onClick = this.onClick.bind(this);
}
textInput = createRef();
onClick(e) {
this.setState({ word: this.textInput.current.value });
}
render() {
return (
<div className="App">
<form>
<input ref={this.textInput} type="text" />
<button onClick={this.onClick} type="button">
Say it!
</button>
</form>
<div>{this.state.word}</div>
</div>
);
}
}
export default App;
check here CodeSandBox
A few things here. First I don't see children as you mention. Moreover, you say obtain state of a children to be used in another children. You have just one parent component here. Then, you are using a <form> which means a button inside will submit the values so you need the escape hatch of e.preventDefault(). Finally, if you must use a class based component instead of functional component, you don't need any more constructor and you can bind your functions with an arrow function. Here is a working example of what I presume you are asking: https://codesandbox.io/s/sleepy-minsky-giyhk

Passing state-based data between pages in React

I am trying to create a multiple page form in React, and I have the basic wireframe set up. I am trying to export a user's Name from one page to the next, but the user will change depending on who has logged in. I've been in google purgatory for a while trying figure out how to grab a specific state-based value out of a component to be available on another page. In my code below, I'm exporting the whole component to render on the App.js page. However, I'd also like to grab just the {userName} to render within another component.
import React, { Component } from 'react'
class Intro extends Component {
state = { userName: ''}
handleChange = (event) => this.setState({ userName: event.target.value })
render() {
const { userName } = this.state
return (
<div id='intro'>
<form>
<FieldGroup
id='nameArea'
value={this.state.value}
onChange={this.handleChange}
/>
<input id='submit' type='submit' value='Submit' /> .
</form>
</div>
)
}
}
export default Intro
To put it simply, you can't. This is where tools like redux come into play. Here's an example using React's new context API:
const UserContext = React.createContext('');
class Intro extends Component {
handleChange = (event) => {
this.props.updateUserName(event.target.value);
}
render() {
const { userName } = this.props
return (
<div id='intro'>
<form>
<input
id='nameArea'
value={userName}
onChange={this.handleChange}
/>
<input id='submit' type='submit' value='Submit' /> .
</form>
</div>
)
}
}
// only doing this to shield end-users from the
// implementation detail of "context"
const UserConsumer = UserContext.Consumer
class App extends React.Component {
state = { userName: '' }
render() {
return (
<UserContext.Provider value={this.state.userName}>
<React.Fragment>
<Intro userName={this.state.userName} updateUserName={(userName) => this.setState({userName})} />
<UserConsumer>
{user => <div>Username: {JSON.stringify(user)}</div>}
</UserConsumer>
</React.Fragment>
</UserContext.Provider>
)
}
}
See my updated codesandbox here.
Most of the time, when you need data on another component, the solution is store the date higher in your component.
As the others already said, the most easy way is trying to pass your state via props from your higher order component to the childs.
Another approach would be to use Redux for your state management. This gives you one global state store accessible from any component.
Third you can try to use the react context api.

React Webpack - Submit Button not retrieving input value on form submit

I'm using webpack with React and I can't for the life of me understand what is going on in this build. This is what's supposed to be happening.
The var headerInput changes to whatever value is inputted onChange.
When the form is submitted(onSubmit) the console.log logs the headerInput value.
The problem: The value that gets console logged is numerical, it's usually something like: .0.0.1. I think it's console.log'ing the click event. Why isn't the value being assigned like in the in the handlerInput function?
Any help is much appreciated.
Thanks, All.
var headerInput = null;
import React from "react";
export default class Navigation extends React.Component{
handlerInput(e,headerInput){
headerInput = e.target.value;
console.log(headerInput);
};
clickSubmit(e,headerInput){
e.preventDefault();
console.log(headerInput);
};
render(){
return(
<form onSubmit={this.clickSubmit.bind(this)}>
<input type="text" placeholder="change header" onChange={this.handlerInput.bind(this)} />
<button>Change Header</button>
</form>
);
}
};
This is not the recommended way to be using React. Instead of relying on a "global" to store your state, you should be using the state API that come with components.
Like so:
import React from "react";
export default class Navigation extends React.Component{
constructor(props) {
super(props);
// Set up your default state here.
this.state = { };
// Do early binding.
this.handlerInput = this.handlerInput.bind(this);
this.clickSubmit = this.clickSubmit.bind(this);
}
handlerInput(e){
// Use setState to update the state.
this.setState({
headerInput: e.target.value
}
};
clickSubmit(e){
e.preventDefault();
// You read state via this.state
console.log(this.state.headerInput);
};
render(){
return(
<form onSubmit={this.clickSubmit}>
/* Make sure you pass the current state to the input */
<input
type="text"
placeholder="change header"
onChange={this.handlerInput}
value={this.state.headerInput}
/>
<button>Change Header</button>
</form>
);
}
};
I definitely recommend you revisit the official react docs, like the thinking in react and react forms tutorials.
If the input is strictly one-way (you only read from it) then just use a ref
import React from "react";
class Navigation extends React.Component{
clickSubmit(e,headerInput){
e.preventDefault();
console.log(this.inputEl.value);
};
render(){
return(
<form onSubmit={this.clickSubmit.bind(this)}>
<input placeholder="change header" ref={el => this.inputEl = el} />
<button>Change Header</button>
</form>
);
}
};
Note that...
Although string refs are not deprecated, they are considered legacy,
and will likely be deprecated at some point in the future. Callback
refs are preferred.
https://facebook.github.io/react/docs/more-about-refs.html

Resources