Reputation: 2155
React newb here. I have a pure function that returns a form (presentation component). In this form I need to handle onChange events for those text fields that are controlled. FWIU, I need to this.setState(...) in my onChange event handlers. However due to this being a pure function, I don't have access to this.setState(). Is there a nice way to set the state on these onChange events in a ES2015 function? I'm also using redux if this helps. Example code:
import React, {PropTypes} from 'react'
const ApplicationForm = ({submitHandler, person}) => (
<form onSubmit={e => submitHandler(e)}>
<div>
<label htmlFor="firstName">First Name:</label>
<input type="text" name="firstName" onChange={e => setState(e.target.value)} value={person.firstName || ''}/>
</div>
...
</form>
)
Upvotes: 5
Views: 9723
Reputation: 43
With React Hooks, we now have state usability extended to functional components as well. To use this, we can import {useState} from React and pass default value into its arguments.
import React, {PropTypes, useState} from 'react'
const ApplicationForm = ({submitHandler, person}) => (
const [name, updateName]= useState(person.firstName);
<form onSubmit={e => submitHandler(e)}>
<div>`enter code here`
<label htmlFor="firstName">First Name:</label>
<input type="text" name="firstName" onChange={e => updateName(e.target.value)} value={name || ''}/>
</div>
...
</form>
)
More details about this can be found in the documentation for useState.
Upvotes: 1
Reputation: 219
You can use react hooks to achieve what you want.
If you write a function component and you want to add some sate to your function, previously you had to change your function into a class. But now you can use react hooks to create your state in your functional component.
EX:- We write class components with state as below
class Foo extends Component {
constructor(props) {
super(props);
this.state = {
age: 20
};
}
now we can achieve above code in function component as followed
import React, { useState } from 'react';
function Foo() {
const [age, setAge] = useState(20);
Refer this document for more details - https://reactjs.org/docs/hooks-state.html
Upvotes: 1
Reputation: 1126
You can actually use setState in something that looks like a functional component, but it's pretty hacky. I imagine this method is something only people who really can't stand using the this keyword and class syntax would ever use. Still, I think it's kind of fun.
Here's how you might write an input that changes another element in a normal way using this and class syntax:
class App extends React.Component {
constructor(props) {
super(props);
this.state = {text: "Hello, world"};
}
handleChange = (event) => {
this.setState({text: event.target.value});
}
render() {
return (
<div>
<input value={this.state.text} onChange={this.handleChange} />
<h1>{this.state.text}</h1>
</div>
)
}
}
And here's how you could create the same effect without this and class syntax:
function App() {
"use strict";
const obj = {
state: {text: "Hello, world"},
__proto__: React.Component.prototype
};
obj.handleChange = function (event) {
obj.setState({text: event.target.value});
};
obj.render = function () {
return (
<div>
<input value={obj.state.text} onChange={obj.handleChange} />
<h1>{obj.state.text}</h1>
</div>
);
};
return obj;
}
The trick is to make the App function inherit from React.Component by setting the dunder proto property of the object App returns to React.Component's prototype so that it can use setState.
Here's a codepen if you want to play around with the code.
Upvotes: 2
Reputation: 4521
Stateless functional components can't have state... because they're stateless. If you want to have event handlers to call and state to set, you will need to create a component class, either via React.createClass
or by using ES6 classes.
Upvotes: 1
Reputation: 5019
That is a Stateless Function, there is no state to set
If you're using redux, you probably want to trigger a redux action in the onChange, passing the new value as an argument, and have the action update the value of firstName in the redux store for person.firstName
I would recommend taking a look at redux-form to reduce a bunch of boilerplate
Upvotes: 9