Reputation: 2002
This seems a silly question, so I apologize in advance.
I have a page with several inputs and at the moment, for some reason, I can't just get the new value written in the input, so I can update the state and send this new data. Seems to me there is something wrong in with the onChange function, because I can get the previous state, but not the new value i'm saving on state.
EDIT: The submit button is outside the input form.
Here is the code:
constructor(props) {
super(props)
this.state = {
editMode: false,
data: {
designation: '',
address: '',
description: ''
}
}
}
componentDidMount = () => {
const dataInfo = data.get('url here');//fetching data here
const data = {
designation: dataInfo.designation ,
address: dataInfo.address,
description: dataInfo.description
}
this.setState({
data: data
})
}
handleInput = (e) => {
let value = e.target.value;
let name = e.target.name;
this.setState(
prevState => ({
data: {
...prevState.data,
[name]: value
}
})
);
}
handleFormSubmit = (e) => {
e.preventDefault();
const { data } = this.state;
console.log('hey', data.designation);
this.setState({
editMode: false
})
}
render() {
{!this.state.editMode
? <button onClick={() => this.setState({ editMode: true })}>edit</button>
: <div>
<button
className={styles.buttonMargin}
onClick={() => this.setState({ editMode: false })}>cancel</button>
<button onClick={this.handleFormSubmit}>Guardar</button>
</div>
}
<div>
{this.state.editMode
? <form onSubmit={this.handleFormSubmit}>
<input
type='text'
placeholder='Nome do Campo'
name='designation'
onChange={this.handleInput}
defaultValue={this.state.data.designation}
/>
</form>
: <p> {this.state.data.designation} </p> }
</div>
}
}
Upvotes: 1
Views: 1762
Reputation: 1821
There are a number of changes that I would recommend, I have a working version of your code here: https://stackblitz.com/edit/react-vmeuxc
Binding your functions inside of constructor will allow you to write unit tests later and also access the functions from outside of your component if needed.
In my experience, using e.currentTarget.value
is more stable than using e.target.value
Difference between e.target and e.currentTarget
I didn't see why you were assigning this.state
to a constant in handleFormSubmit
so I removed that.
You were missing some markup, such as a submit button on your form and an edit button when you weren't in the edit mode. I also don't understand why you had the random this.setState({ editMode: false })
at the end of your render
statement, so I removed that since it wasn't necessary.
Having a helper function such as this would help to examine the existing value to the new one.
compareData(currentData, newData) {
if(currentData === 'undefined' || (newData && currentData !== newData)) {
return newData;
} else {
return false;
}
}
Here's the fully cleaned up version of your code. Note: I had to create a dummy dataInfo
object since I don't have access to your API.
constructor(props) {
super(props);
this.compareData = this.compareData.bind(this);
this.handleInput = this.handleInput.bind(this);
this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.state = {
editMode: false,
data: {
designation: '',
address: '',
description: ''
}
}
}
componentDidMount = () => {
const dataInfo = {
designation: 'test designation',
address: 'test address',
description: 'test description'
};
// const dataInfo = data.get('url here'); //fetching data here
const data = {
designation: dataInfo.designation ,
address: dataInfo.address,
description: dataInfo.description
}
this.setState({
data: data
})
}
compareData(currentData, newData) {
if(currentData === 'undefined' || (newData && currentData !== newData)) {
return newData;
} else {
return false;
}
}
handleInput(e) {
let value = e.currentTarget.value;
let name = e.currentTarget.name;
if(this.compareData(this.state.data[name], value)) {
this.setState({
data: {
...this.state.data,
[name]: value
}
});
}
console.log(this.state);
}
handleFormSubmit(e) {
e.preventDefault();
this.setState({
editMode: false
});
}
render() {
return (
<div>
{!this.state.editMode ? (
<button onClick={() => this.setState({ editMode: true })}>edit</button>
) : (
<div>
<button onClick={() => this.setState({ editMode: false })}>cancel</button>
<button onClick={this.handleFormSubmit}>Guardar</button>
</div>
)}
{this.state.editMode ? (
<form>
<input
type='text'
placeholder='Nome do Campo'
name='designation'
onChange={this.handleInput}
defaultValue={this.state.data.designation}
/>
</form>
) : (
<p> {this.state.data.designation} </p>
)}
</div>
)
}
Upvotes: 1
Reputation: 999
i tweaked your code a little bit. In my case is working, although i suggest you to use value instead of defaultValue for setting the value content of the input component. I had to declare a dummy object instead of fetching the data, and declare your component as a standard HTML field. Also i added a button to enable edit mode since i don't get in which moment you do that. You can test it in codesandbox io (link to working example is https://codesandbox.io/s/n4lpz784wj):
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
editMode: false,
data: {
designation: '',
address: '',
description: ''
}
}
}
componentDidMount = () => {
//const dataInfo = data.get('url here');//fetching data here
const dataInfo = {
designation: "Do something else",
address: "5th Avenue #45",
description: "This is a test description"
}
const data = {
designation: dataInfo.designation,
address: dataInfo.address,
description: dataInfo.description
}
this.setState({
data: data
})
}
handleInput = (e) => {
let value = e.target.value;
let name = e.target.name;
this.setState(
prevState => ({
data: {
...prevState.data,
[name]: value
}
})
);
}
toggleEditionMode = () => {
this.setState({ editMode: true});
}
handleFormSubmit = (e) => {
e.preventDefault();
const { data } = this.state;
console.log('hey', data.designation);
this.setState({
editMode: false
})
}
render() {
console.log(this.state.data.designation);
return (
<div>
{this.state.editMode
? <form onSubmit={this.handleFormSubmit}>
<input
type='text'
placeholder='Nome do Campo'
name='designation'
onChange={this.handleInput}
defaultValue={this.state.data.designation}
/>
</form>
: <p> {this.state.data.designation} <button type="button" onClick={this.toggleEditionMode}>Enable edit</button> </p>}
</div>
);
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Upvotes: 0