Radio button global state for name attribute - javascript

I need to be able to have radion buttons or checkboxes to show / hide content if its checked. There will be more radio buttons and checkboxes to show content in the same form, so to distinguish them from each other, it could be based on the name attribute.
So far i can show the hidden fields when i check the radio buttons, but i want one to cancel out the other, but only if it has the same name attribute (something else can also work).
Is there a react genius who can figure this out? I would be forever in your debt :)
class PartnerRoute extends Component {
constructor(props) {
super(props)
this.state = {
showOneTimeFee: '',
showSubscription: ''
};
}
toggleOneTimeFee = () => {
const currentState = this.state.showOneTimeFee;
this.setState({
showOneTimeFee: !currentState
})
}
toggleSubscription = () => {
const currentState = this.state.showSubscription;
this.setState({
showSubscription: !currentState
})
}
render() {
return (
<div className="partner-route">
<ContentContainer>
<div className="form--create-event">
<form>
<h3>Event information</h3>
<GridContainer columnCount="one">
<CustomInput type="text" placeholder="Event name" />
</GridContainer>
<GridContainer columnCount="one">
<CustomTextarea type="text" placeholder="Event description" />
</GridContainer>
<h3>Event date</h3>
<GridContainer columnCount="three">
<CustomInput type="text" placeholder="Day" />
<CustomInput type="text" placeholder="Month" />
<CustomInput type="text" placeholder="Year" />
</GridContainer>
<h3>Payment</h3>
<GridContainer columnCount="one">
<CustomRadio
type="radio"
name="payment"
id="rb1"
value="1"
label="Free, no payment needed"
/>
<CustomRadio
type="radio"
name="payment"
id="rb2"
value="2"
label="1 time fee"
onChange={this.toggleOneTimeFee}
/>
{this.state.showOneTimeFee &&
<div className="hidden-field">
<CustomInput type="text" placeholder="Price" />
</div>
}
<CustomRadio
type="radio"
name="payment"
id="rb3"
value="3"
label="Subscription"
onChange={this.toggleSubscription}
/>
{this.state.showSubscription &&
<div className="hidden-field">
<CustomInput type="text" placeholder="Price" />
</div>
}
</GridContainer>
</form>
</div>
</ContentContainer>
</div>
)
}
}
export default PartnerRoute

Please check this example where I used setState with prevState that is important and also I used changeHandler for all three radio. Moreover, to run this code in my side I changed all Custom input with generic input for ex CustomInput to input. Please revert this your side.
import React, {Component} from "react";
export default class PartnerRoute extends Component {
constructor(props) {
super(props);
this.state = {
showOneTimeFee: false,
showSubscription: false
};
}
handleChange = (event) => {
if (event.target.value == 2) // One Time Fee
this.setState(prevState => {
return {
showOneTimeFee: !prevState.showOneTimeFee,
showSubscription: false
};
});
else if (event.target.value == 3) // Subscription
this.setState(prevState => {
return {
showOneTimeFee: false,
showSubscription: !prevState.showSubscription
};
});
else // Free, no payment needed
this.setState({
showOneTimeFee: false,
showSubscription: false
});
};
render() {
return (
<div className="partner-route">
<div>
<div className="form--create-event">
<form>
<h3>Event information</h3>
<div>
<input type="text" placeholder="Event name"/>
</div>
<div>
<input type="text" multiline="true" placeholder="Event description"/>
</div>
<h3>Event date</h3>
<div>
<input type="text" placeholder="Day"/>
<input type="text" placeholder="Month"/>
<input type="text" placeholder="Year"/>
</div>
<h3>Payment</h3>
<div>
<input type="radio" name="payment" id="rb1" value="1" label="Free, no payment needed"
onChange={this.handleChange}/>
<label htmlFor="rb1">Free, no payment needed</label><br/>
<input type="radio" name="payment" id="rb2" value="2" label="1 time fee"
onChange={this.handleChange}/>
<label htmlFor="rb2">1 time fee</label><br/>
{this.state.showOneTimeFee &&
<div className="hidden-field">
<input type="text" placeholder="One Time Price"/>
</div>
}
<input type="radio" name="payment" id="rb3" value="3" label="Subscription"
onChange={this.handleChange}/>
<label htmlFor="rb3">Subscription</label><br/>
{this.state.showSubscription &&
<div className="hidden-field">
<input type="text" placeholder="Subscription Price"/>
</div>
}
</div>
</form>
</div>
</div>
</div>
)
}
}

Related

how to Creating a single input handler [duplicate]

This question already has answers here:
Handle change event of all input fields without using refs
(2 answers)
Closed 2 years ago.
I have several inputs ,Each of the inputs has its own value .How can I have a function for (onChange) all of them ?
For example
handleChange1(event) {
this.setState({value1: event.target.value});
}
handleChange2(event) {
this.setState({value2: event.target.value});
}
}
handleChange3(event) {
this.setState({value3: event.target.value});
}
<input type="text" value={this.state.value1} onChange={this.handleChange1} />
<input type="text" value={this.state.value2} onChange={this.handleChange2} />
<input type="text" value={this.state.value3} onChange={this.handleChange3} />
I just want to have one handleChange
When you need to handle multiple controlled input elements, you can add a name attribute to each element and let the handler function choose what to do based on the value of event.target.name.
For example:
handleInputChange(event) {
const target = event.target;
const value = target.type === 'checkbox' ? target.checked : target.value;
const name = target.name;
this.setState({
[name]: value
});
}
render() {
return (
<form>
<label>
value1:
<input
name="value1"
type="checkbox"
checked={this.state.value1}
onChange={this.handleInputChange} />
</label>
<br />
<label>
value2:
<input
name="value2"
type="number"
value={this.state.value2}
onChange={this.handleInputChange} />
</label>
<br />
<label>
value3:
<input
name="value3"
type="text"
value={this.state.value3}
onChange={this.handleInputChange} />
</label>
</form>
);
}
}
If you add a name to the input you can use that off of the event.
handleChange1(event) {
const {name, value} = event.target
this.setState({[name]: value});
}
<input name="inputone" type="text" value={this.state.value1} onChange={this.handleChange1} />
<input name="inputtwo" type="text" value={this.state.value2} onChange={this.handleChange2} />
<input name="inputthree" type="text" value={this.state.value3} onChange={this.handleChange3} />
You can simply do by using input name:
Code:
import React from "react";
import "./styles.css";
class MyComponent extends React.Component {
state = {
value1: "",
value2: "",
value3: ""
};
handleChange = (event) => {
this.setState({ [event.target.name]: event.target.value });
};
render() {
console.log(this.state);
return (
<>
<input
name="value1"
value={this.state.value1}
type="text"
value={this.state.value1}
onChange={this.handleChange}
/>
<input
name="value2"
value={this.state.value2}
type="text"
value={this.state.value2}
onChange={this.handleChange}
/>
<input
name="value3"
value={this.state.value3}
type="text"
value={this.state.value3}
onChange={this.handleChange}
/>
</>
);
}
}
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<MyComponent />
</div>
);
}
Demo: https://codesandbox.io/s/beautiful-brook-p46zs?file=/src/App.js:0-1092
i always do this by switch case
handleChange(event) {
switch (event.target.name) {
case 'name1':
this.setState({ name1: event.target.value });
break;
case 'name2':
this.setState({ name2: event.target.value });
break;
case 'name3':
this.setState({ name3: event.target.value });
break;
default:
break;
}
}
<input type="text" name="name1" value={this.state.value1} onChange={this.handleChange1} />
<input type="text" name="name2" value={this.state.value2} onChange={this.handleChange2} />
<input type="text" name="name3" value={this.state.value3} onChange={this.handleChange3} />
You can use react hooks useState for each field:
const [value1,setvalue1] = useState();
<input type="text" value={value1} onChange={(e)=>setvalue1(e.target.value)}/>
You still do have handle change to each input but you write less code.
You can also look here for more info about react hooks: https://reactjs.org/docs/hooks-state.html
If all inputs are same, I think we can render them dynamically so we don't need to repeat ourself and also make the code more clean.
I think we can have an array of inputs then render dynamically. By using closure, we can have one handleChange function for all inputs.
state={
inputValues: []
}
handleChange(index){
return (event)=>{
this.state.inputValues[index] = event.target.value;
this.setState({inputValues: this.state.inputValues})
}
}
render(){
return this.states.inputValues.map((inputValue, index)=>
<input type="text" value={inputValue} onChange={this.handleChange(index)} />
)
}

Adding array elements through multiple form fields in React

I am working on a quiz app project to learn to react. I came across a situation where I need to store incorrect options in a quiz question in an array. And later pass over the information to the database.
This is an example JSON format.
{
incorrect_answers:["Jeff Bezos","Satya Nadela","Bill Gates"] }
The incorrect answer is an array and the value needs to be inputted through separate text boxes for each incorrect option like this.
option input form
The part where I am stuck is appending them to the array here is my attempt.
export default class CreateQuiz extends Component{
constructor(props){
super(props);
this.onChangedIncorrectAnswer=this.onChangedIncorrectAnswer.bind(this);
this.onSubmit=this.onSubmit.bind(this);
this.state={
incorrect_answers:[]
}
}
onChangedIncorrectAnswer(e){
const option=e.target.value
this.setState({
incorrect_answers:[...this.state.incorrect_answers,option]
});
}
onSubmit(e){
e.preventDefault();
const quiz = {
incorrect_answers:this.state.incorrect_answers
}
console.log(quiz);
axios.post("http://localhost:3000/quizes",quiz)
.then(res=>console.log(res.data));
window.location='/quiz-list';
}
render(){
return (
<div>
<h3>Create New Quiz</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Incorrect Option 1</label>
<input type="text"
required
className="form-control"
value={this.state.incorrect_answers[0]}
onChange={this.onChangedIncorrectAnswer}
/>
</div>
<div className="form-group">
<label>Incorrect Option 2</label>
<input type="text"
required
className="form-control"
value={this.state.incorrect_answers[1]}
onChange={this.onChangedIncorrectAnswer}
/>
</div>
<div className="form-group">
<label>Incorrect Option 3</label>
<input type="text"
required
className="form-control"
value={this.state.incorrect_answers[2]}
onChange={this.onChangedIncorrectAnswer}
/>
</div>
<div className="form-group">
<input type="submit" value="Submit Quiz" className="btn btn-primary"/>
</div>
</form>
</div>
)
}
}
But the form was not working as expected. When I enter content for the first option in the "Option 1" text box only the first character is stored remaining in "Option 2" and so on.
try this, this would work!!
export default class CreateQuiz extends Component {
constructor(props) {
super(props);
this.onChangedCorrectAnswer = this.onChangedCorrectAnswer.bind(this);
this.onChangedIncorrectAnswer = this.onChangedIncorrectAnswer.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
category: "",
correct_answer: "",
difficulty: "",
type: "",
question: "",
incorrect_answers: ["", "", ""]
};
}
onChangedCorrectAnswer(e) {
this.setState({
correct_answer: e.target.value
});
}
onChangedIncorrectAnswer(e, index) {
const option = e.target.value;
const { incorrect_answers } = this.state;
incorrect_answers[index] = option;
this.setState({
incorrect_answers
});
}
onSubmit(e) {
e.preventDefault();
const quiz = {
category: this.state.category,
correct_answer: this.state.correct_answer,
incorrect_answers: this.state.incorrect_answers,
difficulty: this.state.difficulty,
type: this.state.type,
question: this.state.question
};
console.log(quiz);
axios
.post("http://localhost:3000/quizes", quiz)
.then((res) => console.log(res.data));
window.location = "/quiz-list";
}
render() {
return (
<div>
<h3>Create New Quiz</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Correct Answer</label>
<input
type="text"
required
className="form-control"
value={this.state.correct_answer}
onChange={this.onChangedCorrectAnswer}
/>
</div>
<div className="form-group">
<label>Incorrect Option 1</label>
<input
type="text"
required
className="form-control"
value={this.state.incorrect_answers[0]}
onChange={(e) => this.onChangedIncorrectAnswer(e, 0)}
/>
</div>
<div className="form-group">
<label>Incorrect Option 2</label>
<input
type="text"
required
className="form-control"
value={this.state.incorrect_answers[1]}
onChange={(e) => this.onChangedIncorrectAnswer(e, 1)}
/>
</div>
<div className="form-group">
<label>Incorrect Option 3</label>
<input
type="text"
required
className="form-control"
value={this.state.incorrect_answers[2]}
onChange={(e) => this.onChangedIncorrectAnswer(e, 2)}
/>
</div>
<div className="form-group">
<input
type="submit"
value="Submit Quiz"
className="btn btn-primary"
/>
</div>
</form>
</div>
);
}
}
Your array state is considered as one state only
Why don't you create state on the go when user do any change in the input.
create a state object like
this.state = {incorrect_answers: {}}
In your onChangedIncorrectAnswer
onChangedIncorrectAnswer(e){
const option=e.target.value;
const stateName = e.target.name;
this.setState({
incorrect_answers: {...this.state.incorrect_answers, [stateName]: option }
});
}
use your form element as add name as unique which will be used as state
<div className="form-group">
<label>Incorrect Option 1</label>
<input name="incorrect_answers_0" type="text" required className="form-control" value={this.state.incorrect_answers[incorrect_answers_0]}
onChange={this.onChangedIncorrectAnswer} />
</div>
use that object while saving
onSubmit(e){
let yourIncorrectAnswers = Object.values(this.state.incorrect_answers);
})
}

Passing function value from parent to child

I'm building a check builder, I have multiple Parent components (forms) that display their inputs on a Child component (check layout).
This is my parent component:
import React from 'react';
import './../App.css';
import Check from './Check';
class BusinessAddress extends React.Component {
constructor(props) {
super(props);
this.state = {text: {
name: 'BusinessAddress',
a: '',
b: '',
c: '',
d: '',
e: '',
f: '',
g: '',
h: ''
}};
}
handleComponentName = name => {
//console.log('handleComName', name)
return this.state.name === name;
}
handleChange(property, event) {
console.log(event.target.value);
const text = {...this.state.text};
text[property] = event.target.value;
this.setState({text: text});
}
handleSubmit(event) {
console.log(this.state.text.e);
}
render() {
return (
<div>
<div className="form-box">
<h3>Business Address</h3>
<label>Business Name</label>
<input type="text" placeholder="Business Name" value={this.state.text.a} onChange={this.handleChange.bind(this, 'a')} maxLength="30" />
<label>Name Line 2</label>
<input type="text" placeholder="Business Name Line 2" value={this.state.text.b} onChange={this.handleChange.bind(this, 'b')} maxLength="90" />
<label>Street Address</label>
<input type="text" placeholder="Street Address" value={this.state.text.c} onChange={this.handleChange.bind(this, 'c')} maxLength="30" />
<label>Address Line 2</label>
<input type="text" placeholder="Street Address Line 2" value={this.state.text.d} onChange={this.handleChange.bind(this, 'd')} maxLength="30" />
<label>City</label>
<input type="text" className="short" placeholder="City" value={this.state.text.e} onChange={this.handleChange.bind(this, 'e')} maxLength="30" />
<label>State</label>
<input type="text" className="short" placeholder="State" value={this.state.text.f} onChange={this.handleChange.bind(this, 'f')} maxLength="30" />
<label>Postal</label>
<input type="text" className="short" placeholder="Postal" value={this.state.text.g} onChange={this.handleChange.bind(this, 'g')} maxLength="30" />
<label>Phone (optional)</label>
<input type="text" className="short" placeholder="Phone" value={this.state.text.h} onChange={this.handleChange.bind(this, 'h')} maxLength="30" />
</div>
<Check data={this.state.text} handleParent={this.handleComponentName}/>
</div>
)
}
}
export default BusinessAddress;
This is my child component:
import React from 'react';
import './../App.css';
export class Check extends React.Component {
constructor(props) {
super(props);
this.state = {}
}
render() {
const data = Object.values(this.props.data);
if(this.props.handleParent('BusinessAddress')) {
}
return (
<div>
{ data.map((item, index) => <li key={index}>{item}</li>) }
<div id="Address"></div>
<div id="Bank-Info"></div>
</div>
)
}
}
export default Check;
I'm trying to map the data to a specific div based on which parent the data is coming from. Right now all that I'm getting from the child is the returned function, but no return value?
Thanks in advance!
<input type="text" placeholder="Business Name" value={this.state.text.a} onChange={this.handleChange.bind(this, 'a')} maxLength="30" />
Change this to this
<input type="text" placeholder="Business Name" value={this.state.text.a} onChange={(e) => this.handleChange(e, 'a')} maxLength="30" />
also change this
handleComponentName = name => {
//console.log('handleComName', name)
return this.state.name === name; }
to
this.state.text.name === name;
here is the demo
Try binding the onchange like
onChange={(event) => this.handleChange('h', event)}

How to keep track of selections in array of radio button groups?

I'm baffled over this problem that seems to have a simple solution right under my nose, but I can't find it.
I'm looping 42 groups of radio buttons, and I'm only as yet able to get one (out of 42 * 4 buttons) to be selected. I render the first statement, and each statement has 4 choices... Thank you so much for helping.
import React, { Component } from 'react'
class Acme extends Component {
constructor(props) {
super(props);
this.state = {
selections: [],
statements: "forty-two statements+separated by add signs".split('+')
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
// lost here -- ???
handleChange(event) {
this.state.selections.push( event.target.value )
}
handleSubmit(event) {
event.preventDefault()
alert("Hello")
}
render() {
return (
<div className="pure-form">
<h2>Acme</h2>
<hr />
<h3>
Please read each statement and select a number 0, 1, 2 or 3 which indicates how much the statement applied to you <b>over the past week</b>. There are no right or wrong answers. Do not spend too much time on any statement.
</h3>
<form onSubmit={this.handleSubmit}>
{
this.state.statements.map(
(statement, index) => (
<div className="pure-g">
<div className="pure-u-1 pure-u-md-21-24 pure-control-group">
<h4>{index+1}. {statement}</h4>
<div className="pure-u-5-24">
<label className="pure-radio">
<input type="radio" value={0} key={index}
checked={this.state.selections[index] === 0 }
onChange={this.handleChange} />
0
</label>
</div>
<div className="radio pure-u-5-24">
<label className="pure-radio">
<input type="radio" value={1} key={index}
checked={this.state.selections[index] === 1}
onChange={this.handleChange } />
1
</label>
</div>
<div className="radio pure-u-5-24">
<label className="pure-radio">
<input type="radio" value={2} key={index}
checked={this.state.selections[index] === 2 }
onChange={this.handleChange } />
2
</label>
</div>
<div className="radio pure-u-5-24">
<label className="pure-radio">
<input type="radio" value={3} key={index}
checked={this.state.selections[index] === 3 }
onChange={this.handleChange } />
3
</label>
</div>
</div>
</div>
)
)
}
<button type="submit" className="pure-button pure-button-primary">
See Results
</button>
</form>
</div>
)
}
}
export default Acme
You need to keep a map of selections with the key as the statement id. I have attached the sample code
class Acme extends React.Component {
constructor(props) {
super(props);
this.state = {
selections: {},
statements: "forty-two statements+separated by add signs".split('+')
}
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange(event) {
const [id, value] = event.target.value.split('-');
this.setState({
selections: {
...this.state.selections,
[id]: parseInt(value),
}
});
}
handleSubmit(event) {
event.preventDefault()
alert("Hello")
}
render() {
return (
<div className="pure-form">
<h2>Acme</h2>
<hr />
<h3>
Please read each statement and select a number 0, 1, 2 or 3 which indicates how much the statement applied to you <b>over the past week</b>. There are no right or wrong answers. Do not spend too much time on any statement.
</h3>
<form onSubmit={this.handleSubmit}>
{
this.state.statements.map(
(statement, index) => (
<div className="pure-g" key={index}>
<div className="pure-u-1 pure-u-md-21-24 pure-control-group">
<h4>{index+1}. {statement}</h4>
<div className="pure-u-5-24">
<label className="pure-radio">
<input type="radio" value={`${index}-0`} key={`${index}-0`}
checked={this.state.selections[index] === 0 }
onChange={this.handleChange} />
0
</label>
</div>
<div className="radio pure-u-5-24">
<label className="pure-radio">
<input type="radio" value={`${index}-1`} key={`${index}-1`}
checked={this.state.selections[index] === 1}
onChange={this.handleChange } />
1
</label>
</div>
<div className="radio pure-u-5-24">
<label className="pure-radio">
<input type="radio" value={`${index}-2`} key={`${index}-2`}
checked={this.state.selections[index] === 2 }
onChange={this.handleChange } />
2
</label>
</div>
<div className="radio pure-u-5-24">
<label className="pure-radio">
<input type="radio" value={`${index}-3`} key={`${index}-3`}
checked={this.state.selections[index] === 3 }
onChange={this.handleChange } />
3
</label>
</div>
</div>
</div>
)
)
}
<button type="submit" className="pure-button pure-button-primary">
See Results
</button>
</form>
</div>
)
}
}
ReactDOM.render(
<Acme />,
document.getElementById('container')
);
<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="container">
<!-- This element's contents will be replaced with your component. -->
</div>

Keep code DRY on create/edit form

I have a few inputs that are used in my form for both create and update. I decided to make them a component.
// used for CRU on the event record
import React from 'react';
class Form extends React.Component {
render() {
return (
<div className="slds-form">
<div className="slds-form-element">
<label className="slds-form-element__label">Assigned To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.assigned = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Related To</label>
<div className="slds-form-element__control">
<input ref={(input) => this.related = input} type="text" className="slds-input" disabled/>
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Location</label>
<div className="slds-form-element__control">
<input ref={(input) => this.location = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event Start</label>
<div className="slds-form-element__control">
<input ref={(input) => this.start = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Event End</label>
<div className="slds-form-element__control">
<input ref={(input) => this.end = input} type="text" className="slds-input" />
</div>
</div>
<div className="slds-form-element">
<label className="slds-form-element__label">Contact</label>
<div className="slds-form-element__control">
<input ref={(input) => this.contact = input} type="text" className="slds-input" disabled/>
</div>
</div>
<button type="button" className="slds-button slds-button--neutral">Cancel</button>
<button type="submit" className="slds-button slds-button--brand">{this.props.buttonLabel}</button>
</div>
);
}
}
export default Form;
I then attempted to use this component in my <Create /> component.
// used for Create on the event record
import React from 'react';
import Form from './Form';
class Create extends React.Component {
createEvent(e) {
console.log("createEvent() has fired.");
e.preventDefault();
const event = {
assigned: this.assigned.value,
related: this.related.value,
location: this.location.value,
start: this.start.value,
end: this.end.value,
contact: this.contact.value
}
console.log(event);
}
render() {
return (
<form onSubmit={(e) => this.createEvent(e)}>
<Form buttonLabel="Create" />
</form>
);
}
}
export default Create;
When I try to hit the Create button on my <Create /> component I get an error
Uncaught TypeError: Cannot read property 'value' of undefined
at Create.createEvent (webpack:///./src/components/Event/Create.js?:42:32)
at onSubmit (webpack:///./src/components/Event/Create.js?:59:27)
at Object.ReactErrorUtils.invokeGuardedCallback (webpack:///./~/react/lib/ReactErrorUtils.js?:70:16)
at executeDispatch (webpack:///./~/react/lib/EventPluginUtils.js?:89:21)
at Object.executeDispatchesInOrder (webpack:///./~/react/lib/EventPluginUtils.js?:112:5)
at executeDispatchesAndRelease (webpack:///./~/react/lib/EventPluginHub.js?:44:22)
at executeDispatchesAndReleaseTopLevel (webpack:///./~/react/lib/EventPluginHub.js?:55:10)
at Array.forEach (native)
at forEachAccumulated (webpack:///./~/react/lib/forEachAccumulated.js?:25:9)
at Object.processEventQueue (webpack:///./~/react/lib/EventPluginHub.js?:231:7)
I then check the console and see the refs belong in my <Form /> component, and not my <Create /> component.
Is there a way to pass the refs from my child component, <Form />, to its parent, <Create />?
That's a lot of refs! Good news, you really don't need them, at all. As a very very general rule, you should only be using refs if you are interacting with an external library that doesn't "understand" React (d3, Greensock, TinyMCE, etc).
Tackling it in an uncontrolled way can be done like:
const User = (props) => (
<div>
<input name="foo" className="form-control" />
<input name="foo2" className="form-control" />
<button type="submit" className="btn btn-primary">{props.buttonLabel}</button>
</div>
);
class App extends React.Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
}
onChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
onSubmit(e) {
e.preventDefault();
console.log(this.state);
}
render() {
return (
<div className="container">
<br />
<form onChange={this.onChange} onSubmit={this.onSubmit}>
<User buttonLabel="Create"/>
</form>
</div>
);
}
};
ReactDOM.render(<App />, document.getElementById('app'));
Codepen example:
http://codepen.io/cjke/pen/zNXxga?editors=0010

Categories

Resources