Why is my react form not working on codesandbox - javascript

I created a simple form here https://codesandbox.io/s/xenodochial-frog-7squw
It says 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.
But there is an onChange handler being passed, so I don't understand. In addition the page reloads when I hit submit, even though preventDefault() is called
Thank you

The issue is this line:
const { str, handleChange, handleSubmit } = this.state;
handleChange and handleSubmit are not part of the state, but are instance methods, so you can pass them like so:
return (
<div className="App">
<Form str={str} onChange={this.handleChange} onSubmit={this.handleSubmit} />
<Table />
</div>
);

On line 25 you do:
const { str, handleChange, handleSubmit } = this.state;
Because of this, handleChange will be bound to this.state.handleChange which will be undefined as you have no property handleChange in your state.
You also forgot to pass the prop name to your Table-component.
I forked your code and updated it here: https://codesandbox.io/s/modest-meninsky-y1sgh

here is the correct Code for you:
import React from "react";
import "./styles/styles.css";
import Form from "./components/Form";
import Table from "./components/Table";
class App extends React.Component {
constructor(props) {
super(props);
this.state = { str: "", desc: false };
console.log(4444);
this.handleChange = this.handleChange.bind(this); //<-- this binding
}
handleSubmit = event => {
event.preventDefault();
console.log("submitted");
};
handleChange = event => {
this.setState({ str: event.target.value });
};
render() {
const { str } = this.state; // <-- FIXED THIS
return (
<div className="App">
<Form str={str} onChange={this.handleChange} onSubmit={this.handleSubmit} />
<Table />
</div>
);
}
}
export default App;

Related

Confusion around 'value' parameter for <input> tag in REACTjs

I'm a bit confused regarding the 'value' parameter and it's assignment.
From here Can't type in React input text field
I understood that when setting a value parameter, that disables the possibility of entering a value to the input box
YET, if we notice the following code (with a focus on the render method - I will put the whole code in the bottom of this question):
import React, { Component } from 'react'
export default class NewBoxForm extends Component {
constructor(props){
super(props);
this.state = {
height: "",
width: "",
backgroundColor: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(evt){ //handles any form of change in the input.
evt.preventDefault(); // prevents refresh of page
this.setState({
[evt.target.name]: evt.target.value
});
}
handleSubmit(evt){
evt.preventDefault();
console.log(this.state)
this.props.handleSubmit(this.state);
//need to use my parent's function to transfer information to parent.
//for that i will send my state, and he will update his state.
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label htmlFor='height'>Height: </label>
<input
name='height'
id='height'
type="number"
value={this.state.height}
onChange={this.handleChange}
/>
<label htmlFor='width'>Width: </label>
<input
name='width'
id='width'
type="number"
value={this.state.width}
onChange={this.handleChange}
/>
<label htmlFor='backgroundcolor'>BackgroundColor: </label>
<input
name='backgroundcolor'
id='backgroundcolor'
type="text"
value={this.state.backgroundColor}
onChange={this.handleChange}
/>
<button>Submit</button>
</form>
)
}
}
which works!
i'm able this way to insert a value to the input tag..
so, my question is, what is the rule of thumb? what is correct the correct way?
good habit vs bad hobbit (:D)
rest of the code:
import React, { Component } from 'react';
import Box from './Box';
import NewBoxForm from './NewBoxForm';
class BoxList extends Component {
constructor(props){
super(props);
this.state = {
boxes: [
{ width: 10, height: 20, backgroundColor: "red" },
{ width: 20, height: "200px", backgroundColor: "purple" },
{ width: "100px", height: "140px", backgroundColor: "yellow" },
]
};
this.handleSubmit = this.handleSubmit.bind(this);
}
// what i will get from my child(Box) ? A BOX, duh.
handleSubmit(newBox){
this.setState(st => ({
boxes: [...st.boxes, newBox]
}))
console.log(this.state);
}
render() {
let boxes2show = this.state.boxes.map(box => (
<Box
width={box.width}
height={box.height}
backgroundColor={box.backgroundColor}/>
))
return (
<div>
<h1>BoxList</h1>
<NewBoxForm handleSubmit={this.handleSubmit}/>
{boxes2show}
</div>
)
}
}
export default BoxList;
import React, { Component } from 'react'
export default class Box extends Component {
constructor(props){
super(props);
}
render() {
const myStyle = {
backgroundColor: this.props.backgroundColor,
width: `${this.props.width}em`,
height: `${this.props.height}em`
};
return (
<div style={myStyle}>
I'm a box.
sa
</div>
)
}
}
cheers
I think you misunderstood the answer. In React, inputs came in two variants (see Docs):
controlled
uncontrolled
Controlled inputs are given a value={valueState} to it, which prevents any changes from the user if valueState isn't updated inside the component. The following example is a controlled input, that can't be changed, because it has no change event handler:
export default function App() {
const value = 'test';
return (
<div className="App">
<input value={value} />
</div>
);
}
To allow user input, you need to react to changes:
export default function App() {
const [value, setValue] = useState('test')
return (
<div className="App">
<input value={value} onChange={(e) => setValue(e.currentTarget.value)} />
</div>
);
}
On the other hand there are uncontrolled inputs. Those don't receive a value input. But they can receive a defaultValue (React speciality) to allow initialy setting a value to it a user can change:
export default function App() {
const value = "test";
const ref = useRef();
const submit = (e) => {
e.preventDefault();
// get data
console.log(ref.current.value);
};
return (
<form className="App" onSubmit={submit}>
<input defaultValue={value} ref={ref} />
<button>Submit</button>
</form>
);
}

Is it possible to send the state to the page destination at the time of browser back with react-router-dom?

I'm using react.js and react-router-dom to create two pages. Form.js is the page where you enter your name in the form, and Confirmation.js is the page where you confirm the name.
I want to share the state of two classes. So, when you jump to another page from the link button, you will send the state at the same time. The sent state is received in the class constructor as this.state = props.history.location.state.
Many have omitted this code.
//Form.js
import React, { Component } from 'react'
import {Link} from 'react-router-dom'
class Form extends Component {
constructor(props) {
super(props);
const histState = props.history.location.state
this.state = histState == undefined ? {name: this.state} : histState
}
render() {
return (
<div>
<input type="text" onChange={this.handleFormInputChanged} value={this.state.name}/>
<Link to={pathname: "/confirmation" , state: this.state}>Send</Link>
</div>
)
}
}
//Confirmation.js
class Confirmation extends Component {
constructor(props) {
super(props);
this.state = props.history.location.state
}
render() {
return (
<div>
<div>Your Name : <span className="name">{this.state.name}</span></div>
<Link to={pathname: "/form" , state: this.state}>Edit</Link>
</div>
)
}
}
Now I can do what I want to do. However, I noticed that when the user pressed the browser back button on the Confirmation.js page, the state was not sent because it jumped to the Form.js page without pressing the Link component.
As a solution, I added the following code to Confirmation.js.
//Confirmation.js
componentWillUnmount() {
this.props.history.push("/form", this.state)
}
However, when I do a browser back this way and receive a state in the class constructor, props.history.location.state is undefined. And strangely, after a while or reloading, props.history.location.state is set to state normally.
//Form.js
constructor(props) {
...
console.log("Form constructor", props.history.location.state)
}
I want to resolve the time it takes for state to be set as the value of props.history.location.state, is there a solution?
You can pass basic parameters as route segments, like /form/:username, or you could use a query parameter like /form?username=Hiroaki, but passing around data more structured or complex via the url or location history seems inadvisable.
I think you'd save yourself a lot of pain by using context or setting up a simple orthogonal store to keep track of it as the user navigates.
Here's a sketch of how you might do it with context. Assuming the provider is above the router in the component hierarchy, the form state will persist through navigation (though not through page reloads). (I haven't tested any of this code. This is just to give you a sense of it.)
const [formState, setFormState] = useState({});
<FormStateContext.Provider value={formState}>
<Form onChange={setFormState} />
</FormStateContext.Provider>
const Form = ({ onChange }) => {
const formState = useContext(FormStateContext);
return (
<input name="username"
value={formState.username}
onChange={(e) => setFormState({ ...formState, username: e.target.value })}
/>
);
}
const Confirmation = () => {
const formState = useContext(FormStateContext);
return (
<div>Your Name: {formState.username}</div>
);
}
If your components aren't that big, you could do something like this instead of using a different route :
import React from "react";
import { render } from "react-dom";
import "./style.css";
const App = () => {
const [state, setState] = React.useState({isConfirmationMode: false});
const handleChange = e => setState({...state, [e.target.name]: e.target.value});
const confirm = () => {
console.log('confirmed');
// Here send you data or whatever you want
// then redirect wherever you want, I just display the form again
setState({...state, isConfirmationMode: false});
}
const cancel = () => {
// juste display the form again
setState({...state, isConfirmationMode: false});
}
const displayForm = () => (
<div>
name : <input type="text" name="name" value={state.name} onChange={handleChange} />
<button onClick={() => setState({...state, isConfirmationMode: true})}>Send</button>
</div>
);
return state.isConfirmationMode ?
<Confirmation name={state.name} confirm={confirm} cancel={cancel} /> :
displayForm()
};
// Here I created 'confirm' and 'cancel', but you might only need 'cancel'
const Confirmation = ({name, confirm, cancel}) => {
return (
<div>
Are you {name} ?<br />
<button onClick={confirm}>Confirm</button>
<button onClick={cancel}>Cancel</button>
</div>
);
}
render(<App />, document.getElementById("root"));
Here is the repro on Stackblitz. The idea is just to either display the form or a confirmation depending on the state of a simple boolean (I separated the confirmation in another component but here it could be part of the first one).

Passing handleSubmit() to child component does not modify parent's state

I am new to React and Javascript.
I am trying to have a user fill in a form that describes what a "Mob" should look like. When the user hits submit, I expect handleSubmit() (passed in through a parent) to modify the parent's state, which is an object. However, this behavior is not happening.
Here is the parent component, called App.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
mob: new Mob("", "")
};
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
alert("A name was submitted: " + this.state.vnum + " event value: " + event.state.vnum);
const newMob = new Mob(event.state.vnum, event.state.shortDesc);
this.setState({
mob: newMob
});
}
render() {
return (
<div>
<MobForm mob={this.state.mob} onSubmit={() => this.handleSubmit} />
{console.log("parsed mob vnum: " + this.state.mob.vnum)}
</div>
);
}
}
The child component, called MobForm
class MobForm extends React.Component {
render() {
return (
<div>
<form onSubmit={this.props.onSubmit}>
<CreateStringInputField
name="vnum"
label="vnum:"
/>
<CreateStringInputField
name="shortDesc"
label="Short Desc:"
/>
<input type="submit" value="Submit" />
</form>
{console.log(this.state)}
</div>
);
}
}
Which is calling CreateStringInputField()
function CreateStringInputField(props) {
return (
<div name="row">
<label>
<b>{props.label}</b>
<br />
<input
type="text"
name={props.name}
label={props.label}
/>
</label>
</div>
);
}
And, in case it matters, here is what "Mob" looks like.
class Mob {
constructor(vnum, shortDesc) {
this.vnum = vnum;
this.shortDesc = shortDesc;
};
}
I expect to see {console.log("parsed mob vnum: " + this.state.mob.vnum)} print out the vnum as entered by a user. Instead, I see nothing. How can I achieve this expected output?
With React you won't need to work with plain classes. Instead, the class extends a provided React component (Component or PureComponent) or if you don't need state, then'll use plain functions that just return some JSX.
Working example: https://codesandbox.io/s/simple-form-kdh3w
index.js
import React from "react";
import { render } from "react-dom";
import MobForm from "./components/MobForm";
// simple function that returns "MobForm" and it gets rendered by ReactDOM
function App() {
return <MobForm />;
}
// applies "App" to a <div id="root"></div> in the public/index.html file
render(<App />, document.getElementById("root"));
components/MobForm/index.js (stateful parent component)
import React, { Component } from "react";
import Form from "../Form";
const initialState = {
vnum: "",
shortDesc: ""
};
// a stateful parent that manages child state
class MobForm extends Component {
constructor(props) {
super(props);
this.state = initialState;
// since the class fields are normal functions, they'll lose context
// of "this" when called as a callback. therefore, they'll need
// to be bound to "this" -- via bind, "this" is now referring to
// the Class, instead of the global window's "this")
this.handleChange = this.handleChange.bind(this);
this.handleReset = this.handleReset.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
// a reusable class field that stores an input's value via its "name"
// for example: [vnum]: "12345", [shortDesc]: "A number"
// using object destructuring for shorter syntax:
// [event.target.name]: event.target.value
handleChange({ target: { name, value } }) {
this.setState({ [name]: value });
}
// a class field to reset state
handleReset() {
this.setState(initialState);
}
// a class field to "submit" the form and alert what's currently in state
handleSubmit(event) {
// preventDefault prevents page refreshes
event.preventDefault();
// JSON.stringify allows you to print the contents of an object
// otherwise, you'll just see [object Object]
alert(JSON.stringify(this.state, null, 4));
// clears state after submitting form
this.handleReset();
}
render() {
return (
// passing down state via the spread operator, shorthand for
// "vnum={this.state.vum}" and "shortDesc={this.state.shortDesc}",
// as well as, passing down the class fields from above
<Form
{...this.state}
handleChange={this.handleChange}
handleReset={this.handleReset}
handleSubmit={this.handleSubmit}
/>
);
}
}
export default MobForm;
components/Form/index.js (a child function that returns some form JSX)
import React from "react";
import PropTypes from "prop-types";
import Input from "../Input";
// using object destructuring to pull out the MobForm's passed down
// state and fields. shorthand for using one parameter named "props"
// and using dot notation: "props.handleChange", "props.handleReset", etc
function Form({ handleChange, handleReset, handleSubmit, shortDesc, vnum }) {
return (
<form style={{ width: 200, margin: "0 auto" }} onSubmit={handleSubmit}>
<Input name="vnum" label="vnum:" value={vnum} onChange={handleChange} />
<Input
name="shortDesc"
label="Short Desc:"
value={shortDesc}
onChange={handleChange}
/>
<button type="button" onClick={handleReset}>
Reset
</button>{" "}
<button type="submit">Submit</button>
</form>
);
}
// utilizing "PropTypes" to ensure that passed down props match
// the definitions below
Form.propTypes = {
handleChange: PropTypes.func.isRequired,
handleReset: PropTypes.func.isRequired,
handleSubmit: PropTypes.func.isRequired,
shortDesc: PropTypes.string,
vnum: PropTypes.string
};
export default Form;
components/Input/index.js (a reuseable input function)
import React from "react";
import PropTypes from "prop-types";
// once again, using object destructuring to pull out the Form's
// passed down state and class fields.
function Input({ label, name, value, onChange }) {
return (
<div name="row">
<label>
<b>{label}</b>
<br />
<input
type="text"
name={name}
label={label}
value={value}
onChange={onChange}
/>
</label>
</div>
);
}
// utilizing "PropTypes" to ensure that passed down props match
// the definitions below
Input.propTypes = {
label: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
value: PropTypes.string,
onChange: PropTypes.func.isRequired
};
export default Input;
In this line
<MobForm mob={this.state.mob} onSubmit={() => this.handleSubmit} />
you are defining an anonymous function that returns your handleSubmit function.
In your form
<form onSubmit={this.props.onSubmit}>
onSubmit will execute the this.props.onSubmit which just returns the handleSubmit function but it wont execute it. To fix it just change MobForm to pass handleSubmit directly instead of passing it in an anonymous function:
<MobForm mob={this.state.mob} onSubmit={this.handleSubmit} />
To handle the submission correctly you need to convert your form inputs to managed components. See docs here
Something like this would be a good start:
class MobForm extends React.Component {
constructor(props) {
super(props);
this.state = {
vnum: '',
shortDesc: '',
};
this.handleChangeVnum = this.handleChangeVnum.bind(this);
this.handleChangeShortDesc = this.handleChangeShortDesc.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChangeVnum(event) {
this.setState({vnum: event.target.value});
}
handleChangeShortDesc(event) {
this.setState({shortDesc: event.target.value});
}
handleSubmit(event) {
this.props.onSubmit(this.state);
event.preventDefault();
}
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<CreateStringInputField
name="vnum"
label="vnum:"
value={this.state.vnum}
onChange={this.handleChangeVnum}
/>
<CreateStringInputField
name="shortDesc"
label="Short Desc:"
value={this.state.shortDesc}
onChange={this.handleChangeShortDesc}
/>
<input type="submit" value="Submit" />
</form>
{console.log(this.state)}
</div>
);
}
}
And update CreateStringInputField()
function CreateStringInputField(props) {
return (
<div name="row">
<label>
<b>{props.label}</b>
<br />
<input
type="text"
name={props.name}
label={props.label}
value={props.value}
onChange={props.onChange}
/>
</label>
</div>
);
}
I was able to get my desired behavior by passing a function to MobForm which updates this.state.mob.
App
class App extends React.Component {
state = {
mob: new Mob("", "")
};
updateMob = newMob => {
this.setState({
mob: newMob
});
};
render() {
return (
<div>
<MobForm mob={this.state.mob} onSubmit={this.updateMob} />
</div>
);
}
}
I then made MobForm maintain vnum, shortDesc state that I could use in my onChange()
MobForm
state = { vnum: "", shortDesc: "" };
handleSubmit = event => {
event.preventDefault();
const mob = new Mob(this.state.vnum, this.state.shortDesc);
this.props.onSubmit(mob);
};
render() {
return (
<div>
<form onSubmit={this.handleSubmit}>
<CreateStringInputField
name="vnum"
value={this.state.vnum}
onChange={event => this.setState({ vnum: event.target.value })}
/>
<CreateStringInputField
name="short desc"
value={this.state.shortDesc}
onChange={event => this.setState({ shortDesc: event.target.value })}
/>
<input type="submit" value="Submit" />
</form>
</div>
);
}
}

React - Can A Child Component Send Value Back To Parent Form

The InputField & Button are custom components that go into a form to create a form. My issue is how do I send the data back up to form so that on button click, I can fire ajax on the form with data (username & password):
export default auth.authApi(
class SignUpViaEmail extends Component{
constructor(props){
super(props);
this.state = {
email : "",
password : ""
};
this.storeEmail = this.storeEmail.bind( this );
this.storePassword = this.storePassword.bind( this );
}
storeEmail(e){
this.setState({ email : e.target.value });
}
storePassword(e){
this.setState({ password : e.target.value });
}
handleSignUp(){
this.props.handleSignUp(this.state);
}
render(){
return(
<div className="pageContainer">
<form action="" method="post">
<InputField labelClass = "label"
labelText = "Username"
inputId = "signUp_username"
inputType = "email"
inputPlaceholder = "registered email"
inputClass = "input" />
<Button btnClass = "btnClass"
btnLabel = "Submit"
onClickEvent = { handleSignUp } />
</form>
</div>
);
}
}
);
Or Is it not recommended & I should not create custom child components within the form?
child component => InputField
import React,
{ Component } from "react";
export class InputField extends Component{
constructor( props ){
super( props );
this.state = {
value : ""
};
this.onUserInput = this.onUserInput.bind( this );
}
onUserInput( e ){
this.setState({ value : e.target.value });
this.props.storeInParentState({[ this.props.inputType ] : e.target.value });
}
render(){
return <div className = "">
<label htmlFor = {this.props.inputId}
className = {this.props.labelClass}>
{this.props.labelText}
</label>
<input id = {this.props.inputId}
type = {this.props.inputType}
onChange = {this.onUserInput} />
<span className = {this.props.validationClass}>
{ this.props.validationNotice }
</span>
</div>;
}
}
Error : I get the error e.target is undefined on the parent storeEmail func.
React's one-way data-binding model means that child components cannot send back values to parent components unless explicitly allowed to do so. The React way of doing this is to pass down a callback to the child component (see Facebook's "Forms" guide).
class Parent extends Component {
constructor() {
this.state = {
value: ''
};
}
//...
handleChangeValue = event => this.setState({value: event.target.value});
//...
render() {
return (
<Child
value={this.state.value}
onChangeValue={this.handleChangeValue}
/>
);
}
}
class Child extends Component {
//...
render() {
return (
<input
type="text"
value={this.props.value}
onChange={this.props.onChangeValue}
/>
);
}
}
Take note that the parent component handles the state, while the child component only handles displaying. Facebook's "Lifting State Up" guide is a good resource for learning how to do this.
This way, all data lives within the parent component (in state), and child components are only given a way to update that data (callbacks passed down as props). Now your problem is resolved: your parent component has access to all the data it needs (since the data is stored in state), but your child components are in charge of binding the data to their own individual elements, such as <input> tags.
Addendum
In response to this comment:
What if we render a list of the child component? Using this single source of truth in Lifting state up technique will let the parent controls all the state of all the child inputs right? So how can we access each of the value input in the child component to (which is rendered as list) from the parent component?
For this case, you may map a child component for each element in the list. For example:
class Parent extends Component {
//...
handleChangeListValue = index => event => {
this.setState({
list: this.state.list
.map((element, i) => i === index ? event.target.value : element)
});
}
//...
render() {
return this.state.list.map((element, i) => (
<Child
value={element}
onChangeValue={this.handleChangeListValue(i)}
/>
));
P.S. Disclaimer: above code examples are only for illustrative purposes of the concept in question (Lifting State Up), and reflect the state of React code at the time of answering. Other questions about the code such as immutable vs mutable array updates, static vs dynamically generated functions, stateful vs pure components, and class-based vs hooks-based stateful components are better off asked as a separate question altogether.
React class component
Parent.js
import React, { Component } from 'react';
import Child from './child'
class Parent extends Component {
state = {
value: ''
}
onChangeValueHandler = (val) => {
this.setState({ value: val.target.value })
}
render() {
const { value } = this.state;
return (
<div>
<p> the value is : {value} </p>
<Child value={value} onChangeValue={this.onChangeValueHandler} />
</div>
);
}
}
export default Parent;
Child.js
import React, { Component } from 'react';
class Child extends Component {
render() {
const { value , onChangeValue } = this.props;
return (
<div>
<input type="text" value={value} onChange={onChangeValue}/>
</div>
);
}
}
export default Child;
React hooks
Parent.js
import { useState } from "react";
import Child from "./child";
export default function Parent() {
const [value, changeValue] = useState("");
return (
<div>
<h1>{value}</h1>
<Child inputValue={value} onInputValueChange={changeValue} />
</div>
);
}
Child.js
export default function Child(props) {
return (
<div>
<input
type="text"
value={props.inputValue}
onChange={(e) => props.onInputValueChange(e.target.value)}/>
</div>
);
}
Parent.js
import SearchBar from "./components/SearchBar";
function App() {
const handleSubmit = (term) => {
//Log user input
console.log(term);
};
return (
<div>
<SearchBar onPressingEnter={handleSubmit} />
</div>
);
}
export default App;
Child.js
import { useState } from "react";
function SearchBar({ onPressingEnter }) {
const [UserSearch, setname] = useState("[]");
/* The handleChange() function to set a new state for input */
const handleChange = (e) => {
setname(e.target.value);
};
const onHandleSubmit = (event) => {
//prevent form from making a http request
event.preventDefault();
onPressingEnter(UserSearch);
};
return (
<div>
<form onSubmit={onHandleSubmit}>
<input
type="search"
id="mySearch"
value={UserSearch}
onChange={handleChange}
name="q"
placeholder="Search the site…"
required
/>
</form>
</div>
);
}
export default SearchBar;
You can add a "ref name" in your InputField so you can call some function from it, like:
<InputField
ref="userInput"
labelClass = "label"
labelText = "Username"
inputId = "signUp_username"
inputType = "email"
inputPlaceholder = "registered email"
inputClass = "input" />
So you can access it using refs:
this.refs.userInput.getUsernamePassword();
Where getUsernamePassword function would be inside the InputField component, and with the return you can set the state and call your props.handleSignUp

Are props passed from parent components available only in render?

I'm struggling to understand where I can use props passed by parent's component. It seems that the props are available only in render() method.
The piece of code below is working perfectly but I can't easily serialize the form data and do "e.preventDefault()" thing (can I?)...it'd be better written in const Form = props => { ... })
class Form extends Component {
render() {
const {
handleSubmit
} = this.props;
return (
<div>
<form
onSubmit={this.props.handleSubmit.bind(this)}
>
<TextInput />
<button className="Button">Add</button>
</form>
</div>
);
}
}
BUT this does not work (props are not available in onSubmit method):
class Form extends Component {
onSubmit(e) {
e.preventDefault();
const data = ... serialized form data;
this.props.handleSubmit(data);
}
render() {
return (
<div>
<form
onSubmit={this.onSubmit}
>
<TextInput />
<button className="Button">Add</button>
</form>
</div>
);
}
}
Am I misunderstanding some react.js approach? Is there possibly some .bind(this) missing?
Thanks in advance.
Is there possibly some .bind(this) missing?
Yes you need/can use .bind, or use arrow functions, because now this does not refer to Form
class Form extends Component {
constructor() {
super();
this.onSubmit = this.onSubmit.bind(this)
}
...
}
or just use arrow function
<form
onSubmit={ (e) => this.onSubmit(e) }
>

Categories

Resources