Render html based on the radio select - reactjs

I have two radio buttons and need to render a different form for each when the user click the continue button, how can I do this? Here's the code I have so far.
class App extends Component {
constructor() {
super();
this.state = {
name: "typeOfInternet"
};
this.onChangeValue = this.onChangeValue.bind(this);
}
onChangeValue(event) {
console.log(event.target.value);
}
handleChange = () =>
this.setState({ showComponent: !this.state.showComponent });
render() {
return (
<Container>
<section className="section">
<div className="tittle">
<span>
Vamos começar? Escolha a modalidade e preencha seus dados para
continuar.
</span>
</div>
<div className="check-block" onChange={this.onChangeValue}>
<div className="check">
<input
type="radio"
id="residencia"
name="internet"
value="residencial"
/>
<label for="residencial">Internet Residencial</label>
</div>
<div className="check">
<input
type="radio"
id="empresa"
name="internet"
value="empresarial"
/>
<label for="empresarial">Internet Empresarial</label>
</div>
</div>
<div className="continue">
<button
className="btn-continue"
>
Continue
</button>
</div>
</section>
</Container>
)
}
}
export default App ;
The difference between codes are some input fields that "imternet Empresarial" has and "Internet Residencial" does not

There is no need for onChangeValue function because you're not calling it anywhere instead you can attach handleChange function to the <input> tags.
You should use the name which is provided in <input> inside state. So that it will be easier to use in setState.
There's no need to use .bind() also, with the help of arrow functions => you can escape that.
Inside switch, on different cases of the values instead of using <div>...</div>, you can call different components present in separate file. (in order to make the component readable)
Codesandbox Demo
import { Component } from "react";
class App extends Component {
constructor(props) {
super(props);
this.state = {
internet: ""
};
}
handleChange = (e) => this.setState({ [e.target.name]: e.target.value });
renderForm = () => {
switch (this.state.internet) {
case "residencial":
return (
<div>
<h1>residencial form</h1>
</div>
);
case "empresarial":
return (
<div>
<h1>empresarial form</h1>
</div>
);
default:
return null;
}
};
render() {
return (
<section className="section">
<div className="tittle">
<span>
Vamos começar? Escolha a modalidade e preencha seus dados para
continuar.
</span>
</div>
<div className="check-block" onChange={this.onChangeValue}>
<div className="check">
<input
type="radio"
id="residencia"
name="internet"
value="residencial"
onChange={this.handleChange}
/>
<label htmlFor="residencial">Internet Residencial</label>
</div>
<div className="check">
<input
type="radio"
id="empresa"
name="internet"
value="empresarial"
onChange={this.handleChange}
/>
<label htmlFor="empresarial">Internet Empresarial</label>
</div>
</div>
{this.renderForm()}
<div className="continue">
<button className="btn-continue">Continue</button>
</div>
</section>
);
}
}
export default App;

First, you need to create your form element to render when radio buttons get toggled. Something like this:
const Form = ({ type }) => {
return type === "residencial" ? <div>Form 1</div> : <div>Form 2</div>;
};
Then keep track of the currently checked radio button and whether or not the continue button has been pressed. Something like this would work (Sandbox):
const Form = ({ type }) => {
return type === "residencial" ? <div>Form 1</div> : <div>Form 2</div>;
};
class App extends Component {
constructor() {
super();
this.state = {
name: "",
step: 1
};
}
onChangeValue = (event) => {
console.log(event.target.value);
this.setState({ name: event.target.value });
};
handleContinue = () => {
this.setState({ step: 2 });
};
render() {
const { step, name } = this.state;
return (
<div>
<section className="section">
<div className="tittle">
<span>
Vamos começar? Escolha a modalidade e preencha seus dados para
continuar.
</span>
</div>
<div className="check-block">
<div className="check">
<input
type="radio"
id="residencia"
name="internet"
value="residencial"
onChange={this.onChangeValue}
/>
<label for="residencial">Internet Residencial</label>
</div>
<div className="check">
<input
type="radio"
id="empresa"
name="internet"
value="empresarial"
onChange={this.onChangeValue}
/>
<label for="empresarial">Internet Empresarial</label>
</div>
</div>
<div className="continue">
<button
disabled={name === ""}
className="btn-continue"
onClick={this.handleContinue}
>
Continue
</button>
<hr />
{step === 2 ? <Form type={name} /> : null}
</div>
</section>
</div>
);
}
}
export default App;
There is also no need to bind your class functions, just use arrow functions, they will make your life much easier.

Related

Instead of storing values to local storage want to store values in Redux how can i Do?

Hello I am using class component in react JS.Instead of storing values to local storage store values in Redux how can i Do?How can we implement this in react JS. Below I am sharing my code.Please check my where I am doing wrong?
import React, {Component} from 'react';
import Header from '../Header';
import {connect} from 'react-redux';
class Step5 extends Component {
constructor(){
super()
this.state = {estimated:'1-2'}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
const { estimated, value } = event.target;
console.log('JJF',event.target.value)
this.setState({
selectedOption: event.target.value
});
};
handleSubmit = (e) => {
e.preventDefault();
var step5 = this.state.estimated;
console.log('estimated', JSON.stringify(step5))
console.log('step5',step5);
localStorage.setItem('step5', step5);
const data = {
id: new Date(),
step5:step5
}
this.props.dispatch({type:'ADD_STEP5',data});
window.open("/Step6" , "_self");
}
render(){
const {value} =this.state;
return(
<div>
<Header />
<section className="planing_outer">
<form onSubmit={this.handleSubmit}>
<h1>{value} fff</h1>
<div className="container">
<div className="inner_heading">
<h4>How big is your event?</h4>
</div>
<div className="row">
<div className="col-lg-8 offset-lg-2">
<div className="text_outer"># of Estimated Attendees</div>
<div className="row">
<div className="col-lg-4 col-md-4">
<div className="even_box1">
<input type="radio" className="ischeck" id="flexCheckDefault" checked={this.state.selectedOption==="1-20"} value="1-20" name="estimated" onChange={this.handleChange}/><h3>1-20</h3>
</div>
</div>
<div className="col-lg-4 col-md-4">
<div className="even_box1">
<input type="radio" className="ischeck" id="flexCheckDefault" checked={this.state.selectedOption==="21-50"} value="21-50" name="estimated" onChange={this.handleChange}/><h3>21-50</h3>
</div>
</div>
<div className="col-lg-4 col-md-4">
<div className="even_box1">
<input type="radio" className="ischeck" id="flexCheckDefault" value="50+" checked={this.state.selectedOption==="50+"} name="estimated" onChange={this.handleChange}/><h3>50+</h3>
</div>
</div>
</div>
<div className="text_outer atten">You can always edit it later</div>
<div className="btn_outer">
<button type='submit' className='btn btn-primary'> Continue </button>
{/* <button type='submit' className='btn btn-primary' disabled={btnDisabled} onClick={redirectNewStep}> Continue </button> */}
{/* Continue */}
</div>
</div>
</div>
</div>
</form>
</section>
</div>
)
}
}
export default connect()(Step5);
In this I am using radio button on submit how we check radio button is checked not. If check store their value in redux and local storage .
You are storing your selected value in selectedOption, retrieving that state in hadleSubmit should work fine:
handleSubmit = (e) => {
e.preventDefault();
const selected = this.state.selectedOption;
if (!selected) {
alert('Please select an estimate')
return
}
localStorage.setItem('step5', selected);
const data = {
id: new Date(),
step5: selected,
};
this.props.dispatch({ type: 'ADD_STEP5', data });
window.open('/Step6', '_self');
};
You are setting the value of selected radio button in the state variable selectedOption. You are assigning event.target.value to selectedOption, so selectedOption will either have value '21-50' or '50+' You just need to check if selectedOption is defined in your handleSubmit function
handleSubmit = (e) => {
e.preventDefault();
var step5 = this.state.selectedOption;
if(step5)
localStorage.setItem('step5', step5);
const data = {
id: new Date(),
step5:step5
}
this.props.dispatch({type:'ADD_STEP5',data});
window.open("/Step6" , "_self");
}

Updating a list of options in the child when updating the parent state

My list of options (domains) based on the selected course is updated in the parent state, but the child won't update/inherit the prop sent with it. The child needs to receive the domains state from the parent and make up a option list out of it. It works on initialize, but won't update after the change of course in the parent component.
AddQuestion.js
class AddQuestion extends Component {
constructor(props){
super(props)
// initiate all states
this.state = {
course: '',
domains: []
}
}
render() {
return (
<MainQuestion formError={this.state.formError} levels={this.state.levels} years={this.state.years} courses={this.state.courses} introductionlist={this.state.introductionlist} subQuestions={this.state.subQuestions} numSubQuestion={this.state.numSubQuestion} handleCourseChange={this.handleCourseChange} postQuestion={this.postQuestion} addSubQuestion={this.addSubQuestion} formHasError={this.state.formHasError} validateForm={this.validateForm}/>
);
}
// handle onchange course input
handleCourseChange = (e) => {
this.setState({
course: e.target.value
},
function(e) {
console.log(this.state.course);
this.getResponseDomains();
},
this.validateForm(e)
);
}
// get domains based on course
getResponseDomains = () => {
console.log(this.state.course);
// fetch data from backend
axios.get('/api/domain/get?course=' + this.state.course, {
course: this.state.course
})
.then(response => response.data.data)
.then((json) => {
json.map(obj => this.setState({domains: Object.values(obj) }));
this.state.domains = json;
// map a option input for each fetched domain
let domainslist = Object.keys(this.state.domains).map(key =>
<option label={this.state.domains[key].name} value={this.state.domains[key].id} />
)
this.setState({
domains: domainslist
});
})
.catch((error) => {
console.log(error);
});
}
// Add the input field to a new subquestion
addSubQuestion = () => {
this.setState({
numSubQuestion: this.state.numSubQuestion + 1,
formHasError: true
});
//reset array
subQuestions = [];
let errormessages = '';
let errornum = this.state.numSubQuestion + 1;
//fill array for amount of subquestions needed
for (var i = 0; i <= this.state.numSubQuestion; i += 1) {
subQuestions.push(<SubQuestion key={i} number={i + 1} domain={this.state.domain} course={this.state.course} domains={this.state.domains} subjects={this.state.subjects} />);
this.setState({
subQuestions: subQuestions,
formError: errormessages
});
}
MainQuestion.js
// This is the main question (e.d. level, year, course and introduction)
class MainQuestion extends Component {
constructor(props){
super(props)
}
render() {
return (
<div className="addQuestion-wrapper">
<div className="logo mx-auto">
<img src="/img/logo-white.png"/>
</div>
<section className="addQuestion container">
<form id="addQuestionForm">
<p className="text-danger">{ this.props.formError }</p> {/* display errors */}
<div className="row d-flex prequestion">
<div className="col-12 mb-3">
<h2>Nieuwe vraag toevoegen</h2>
</div>
<div ref="error3" className="input-group col-12 col-lg-6" id="levels-wrapper">
<div>
<p className="label">Niveau</p>
{this.props.levels} {/* display fetched levels */}
</div>
</div>
<div ref="error4" className="input-group col-12 col-lg-6" id="years-wrapper">
<div>
<p className="label">Leerjaar</p>
{this.props.years} {/* display fetched years */}
</div>
</div>
<div ref="error5" className="input-group col-12 col-lg-6">
<p className="label">Vak</p>
<select onChange={this.props.handleCourseChange} name="course" id="select-courses">
<option value="" disabled selected>--Kies een vak</option>
{this.props.courses} {/* display fetched courses */}
</select>
</div>
<div ref="error10" className="input-group col-12 col-lg-12">
{this.props.introductionlist} {/* display created introduction textarea */}
</div>
</div>
{ this.props.subQuestions } {/* display amount of subquestions in the array */}
{/* add subquestion button */}
<div className="AddSubquestion">
<button className="btn" onClick={ this.props.addSubQuestion } disabled={this.props.formHasError}>Subvraag toevoegen</button>
</div>
{/* post question button */}
<div className="input-group" id="submit">
<button className="btn" onClick={ this.props.postQuestion } value="Aanmaken" disabled={this.props.formHasError}>Verzend</button>
</div>
</form>
</section>
</div>
);
}
}
export default AddQuestion;
SubQuestion.js
class SubQuestion extends Component {
constructor(props){
super(props)
// initiate all states
this.state = {
course: props.course,
domains: []
}
}
render() {
return (
<div className="row d-flex justify-content-center question mt-5">
<div className="col-12">
<h3> Subvraag {this.props.number} </h3> {/* display number of subquestion. Fetched from key of created child component */}
</div>
<div ref="error" className="input-group col-12 col-lg-6" id="type-wrapper">
{this.state.type} {/* display fetched type */}
</div>
<div ref="error2" className="input-group col-12 col-lg-6" id="questionings-wrapper">
<div>
<p className="label">Vraagstelling</p>
{this.state.questionings} {/* display fetched questionings */}
</div>
</div>
<div ref="error6" className="input-group col-12 col-lg-12">
{this.state.question} {/* display created textarea for questiona AND answer */}
</div>
<div ref="error7" className="input-group col-12 col-lg-6">
<p className="label">Domein</p>
<select id="select-domains" name={`domain-${this.props.number}`} onChange={this.handleDomainChange}>
<option value="" disabled selected>--Kies een domein</option>
{this.props.domains} {/* display fetched domains */}
</select>
</div>
<div ref="error8" className="input-group col-12 col-lg-6" id="select-subjects">
<p className="label">Onderwerp</p>
<select onChange={this.props.handleSubjectChange} name={`subject-${this.props.number}`}>
<option value="" disabled selected>--Kies een onderwerp</option>
{this.state.subjects} {/* display fetched subjects */}
</select>
</div>
<div ref="error9" className="input-group col-12 col-lg-12" id="time-points-rtti">
<div className="time mr-4">
{/* display time input */}
<p className="label">Tijdsduur</p>
<input type="number" name={`tijdsduur-${this.props.number}`} min="1" placeholder="tijd in minuten" onChange={this.props.handleTimeChange}/>
</div>
<div className="points mr-4">
{/* display points input */}
<p className="label">Punten</p>
<input type="number" name={`points-${this.props.number}`} min="1" placeholder="punten" onChange={this.props.handlePointsChange}/>
</div>
<div className="rtti">
{/* display rtti input */}
<p className="label">RTTI</p>
<input type="radio" name={`RTTI-${this.props.number}`} id={`R-${this.props.number}`} value="1" onChange={this.props.handleRttiChange}/><label htmlFor={`R-${this.props.number}`}>R</label>
<input type="radio" name={`RTTI-${this.props.number}`} id={`T1-${this.props.number}`} value="2" onChange={this.props.handleRttiChange}/><label htmlFor={`T1-${this.props.number}`}>T1</label>
<input type="radio" name={`RTTI-${this.props.number}`} id={`T2-${this.props.number}`} value="3" onChange={this.props.handleRttiChange}/><label htmlFor={`T2-${this.props.number}`}>T2</label>
<input type="radio" name={`RTTI-${this.props.number}`} id={`I-${this.props.number}`} value="4" onChange={this.props.handleRttiChange}/><label htmlFor={`I-${this.props.number}`}>I</label>
</div>
</div>
</div>
);
}
componentWillReceiveProps(nextProps) {
this.setState({course: nextProps.course, domains: nextProps.domains });
}
// handle onchange domain input
handleDomainChange = (e) => {
this.setState({
domain: e.target.value
},
this.getResponseSubjects, // change subjects based on selected domain
this.props.validateForm(e)
);
}
// get subjects based on domain
getResponseSubjects = () => {
// fetch data from backend
axios.get('/api/subject/get?domain=' + this.state.domain, {
domain: this.state.domain
})
.then(response => response.data.data)
.then((json) => {
json.map(obj => this.setState({subjects: Object.values(obj) }));
this.state.subjects = json;
// map a option input for each fetched subject
let subjectslist = Object.keys(this.state.subjects).map(key =>
<option label={this.state.subjects[key].name} value={this.state.subjects[key].id} />
)
this.setState({
subjects: subjectslist
}
);
})
.catch((error) => {
console.log(error);
});
}
export default SubQuestion;
The expected result would be the child component changing the domains based on the course. These variables are changed the parent AddQuestion, but don't come thru as prop in the child.
At first glance you're doing this:
handleCourseChange = (e) => {
this.setState({
course: e.target.value
},
function(e) {
console.log(this.state.course);
this.getResponseDomains();
},
this.validateForm(e)
);
}
If I'm right that callback after setState doesn't know what this is, because you're declaring a full function instead of an arrow function. Regular functions don't inherit this, they have it undefined by default.
I fixed it by calling the addSubQuestion function on handleCourseChange(). This forced the subquestions to re-render.

Reactjs - Submitting multiple lines from one textarea

I'm trying to allow a textarea to take a list of names and display the submission of names on the page. However, I want the user to only be able to submit one name per line.
How would one go about this? More specifically, how would one grab the line breaks and split them into, say... an array to be mapped through and displayed in a dom element.
In my code the state of names is an empty string, but I think it would be easier/more manageable if it were an array.
Thanks!
class Content extends Component {
constructor(props) {
super(props);
this.state = {
names: ""
};
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
handleSubmit = (e) => {
e.preventDefault();
}
handleChange = (e) => {
this.setState({
names: e.target.value
});
}
render() {
return (
<section className="flex">
<div className="content flex">
<div className="sandbox flex">
<div className="directions">
<h1>Please enter a list of names.</h1>
<h3>Select a langauge at the top of the page.</h3>
</div>
<form id="nameForm" className="names flex">
<div className="form-group">
<textarea
id="names"
name="hard"
value={this.state.names}
cols={20}
rows={20}
onChange={this.handleChange}
wrap="hard">
</textarea>
</div>
</form>
<button id="formButton" form="nameForm" type="submit">Submit</button>
<div className="nametags flex">
<div className="nametags-group flex">
<button type="button" className="nametag">{this.state.names}</button>
<p className="greeting">Hello there, happy to see you back!</p>
</div>
<div className="nametags-group flex">
<button type="button" className="nametag">John Doe</button>
<p className="greeting">Hello there, happy to see you back!</p>
</div>
</div>
</div>
</div>
</section>
)
}
}
export default Content;
This code should work perfectly for you:
import React, { Component } from 'react'
class Content extends Component {
constructor(props) {
super(props)
this.state = {
names: ''
}
this.handleSubmit = this.handleSubmit.bind(this)
this.handleChange = this.handleChange.bind(this)
}
handleSubmit = name => {
alert(`Submitted name: ${name}`)
}
handleChange = e => {
this.setState({
names: e.target.value
})
}
render() {
return (
<section className="flex">
<div className="content flex">
<div className="sandbox flex">
<div className="directions">
<h1>Please enter a list of names.</h1>
<h3>Select a langauge at the top of the page.</h3>
</div>
<form id="nameForm" className="names flex">
<div className="form-group">
<textarea
id="names"
name="hard"
value={this.state.names}
cols={20}
rows={20}
onChange={this.handleChange}
wrap="hard"
/>
</div>
</form>
<button id="formButton" form="nameForm" type="submit">
Submit
</button>
<div className="nametags flex">
<div className="nametags-group flex">
{this.state.names
.split('\n')
.filter(n => n) // to filter out empty names
.map((name, index) => (
<button
key={index}
type="button"
className="nametag"
onClick={() => this.handleSubmit(name)}
>
{name}
</button>
))}
<p className="greeting">Hello there, happy to see you back!</p>
</div>
</div>
</div>
</div>
</section>
)
}
}
export default Content
I think it's easier to keep the name state as string.
When rendering the names, split the string at \n, filter out the empty names (basically those extra newlines without names), and render the rest.
When clicking on those name buttons, call handleSubmit and pass name as argument.
So the rest to do is what you want to do with those names in handleSubmit.
Something like this:
handleChange = e => {
this.setState({
names: e.target.value,
submitNames: e.target.value.split(/\r?\n/)
});
};
And change how you display buttons:
{ this.state.submitNames.map(
(name) =>
<button
onClick={() => this.handleSubmit(name)}
type="button"
className="nametag"
>
{name}
</button>
)}

How to accept and pass two parameter as props

Hi I need to pass two parameters, to the class Chat. Currently it is getting only one parameter and displaying correctly.
const Chat = props => (
<div >
<ul>{props.messages.map(message => <li key={message}>{message}</li>)}</ul>
</div>
);
This Chat.js file is called from the Home.js. Suppose I need to pass the Chat component two parameters and I tried it like following.
import React, { Component } from 'react';
import { User } from './User';
import Chat from './Chat';
export class Home extends Component {
displayName = Home.name
state = {
messages: [],
names: []
};
handleSubmit = (message,name) =>
this.setState(currentState => ({
messages: [...currentState.messages, message],
names: [...currentState.names,name]
}));
render() {
return (
<div>
<div>
<User onSubmit={this.handleSubmit} />
</div>
<div>
<Chat messages={this.state.messages,this.state.name} />
</div>
</div>
);
}
}
In this scenario how should I change the Chat component to accept two parameters and display inside div tags.
This is what I tried. But seems it is incorrect.
const Chat = props => (
<div >
<ul>{props.messages.map((message, name) => <li key={message}>{message}</li> <li key={name}>{name}</li>)}</ul>
</div>
);
PS: The User Method
import * as React from 'react';
export class User extends React.Component{
constructor(props) {
super(props);
this.state = {
name: '',
message: ''
}
this.handleSubmit = this.handleSubmit.bind(this);
this.handleChange = this.handleChange.bind(this);
}
render() {
return (
<div className="panel panel-default" id="frame1" onSubmit={this.handleSubmit}>
<form className="form-horizontal" action="/action_page.php" >
<div className="form-group">
<label className="control-label col-sm-2" htmlFor="name">Your Name </label>
<div className="col-sm-10">
<input type="text" className="form-control" name="name" placeholder="Enter your Name" onChange={this.handleChange} />
</div>
</div>
<div className="form-group">
<label className="control-label col-sm-2" htmlFor="message">Message</label>
<div className="col-sm-10">
<input type="text" className="form-control" name="message" placeholder="Enter your Message" onChange={this.handleChange}/>
</div>
</div>
<div className="form-group">
<div className="col-sm-offset-2 col-sm-10">
<button type="submit" id="submit" className="btn btn-default">Submit</button>
</div>
</div>
</form>
</div>
);
}
handleChange(evt) {
this.setState({ [evt.target.name]: evt.target.value });
}
handleSubmit = (e) => {
e.preventDefault();
this.props.onSubmit(this.state.message, this.state.name);
this.setState({ message: "" });
this.setState({name:""});
};
}
You can do this by using separate attributes to pass different props. So for instance, you might revise your <Home/> components render method like so:
<Chat messages={this.state.messages} names={this.state.names} />
and then to access these two bits of data (messages and name) from inside the <Chat /> component you could do the following:
const Chat = props => (
<div >
<ul>{props.messages.map((message, index) => <li key={message}>
From: { Array.isArray(props.names) ? props.names[index] : '-' }
Message: {message}</li>)}
</ul>
</div>
);
Hope this helps!
You have to pass them separately:
<Chat messages={this.state.messages} name={this.state.name} />

Editing input fields in react seeding with default

I have a bootstrap modal where a user is supposed to edit what he entered in a table. When I set-state using static getDerivedStateFromProps, the user cannot modify the input box, but when I manually initialize the state with some arbitrary data, the user can modify it. What am I doing wrong?
the component is getting its props from redux.
export default class EditItem extends Component {
constructor(props) {
super(props);
this.state = {
name: ""
};
}
handleChange = (event) => {
let { value, name } = event.target;
this.setState({
[name]: value
})
}
static getDerivedStateFromProps(nextProps, prevState){
return {
name: nextProps.itemDetails.name
}
}
render() {
let {
} = this.state;
let {itemDetails} = this.props
return (
<div id="myModal3" className="modal fade">
<div id={uuidv1()} className="modal-dialog">
<div id={uuidv1()} className="modal-content">
<div id={uuidv1()} className="modal-body">
<form id={uuidv1()} className="form-horizontal form-material">
{this.props.cat_name}
<div id={uuidv1()} className="form-group">
<label id={uuidv1()} className="col-md-8">
Item Name
</label>
<div id={uuidv1()} className="col-md-8">
<input
id={uuidv1()}
onChange={this.handleChange}
value={this.state.name}
name="name"
type="text"
placeholder="ex. Burrito"
className="form-control form-control-line"
/>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
Using getDrivesStateToProps is not a good option like that. You have a prop, why don't you use it directly? You can look here for more explanation.
Set your initial state to your prop:
class App extends React.Component {
constructor( props ) {
super( props );
this.state = {
name: this.props.itemDetails.name,
};
}
handleChange = ( event ) => {
const { value, name } = event.target;
this.setState( {
[ name ]: value,
} );
};
render() {
let { } = this.state;
const { itemDetails } = this.props;
console.log( this.state );
return (
<div>
<div>
<div>
<div>
<form>
{this.props.cat_name}
<div>
<label>Item Name</label>
<div>
<input
onChange={this.handleChange}
value={this.state.name}
name="name"
type="text"
placeholder="ex. Burrito"
className="form-control form-control-line"
/>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
);
}
}
const itemDetails = { name: "foo" };
ReactDOM.render(<App itemDetails={itemDetails}/>, document.getElementById("root"));
<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="root"></div>
If your prop is coming from an async operation, I don't know maybe you can use something like this just to be in the safe side:
this.state = {
name: ( this.props.itemDetails && this.props.itemDetails.name ) || "",
};
Maybe there is a better way ¯(°_o)/¯

Resources