staxwell staxwell - 8 days ago 6
Javascript Question

Editing text in React

I'm trying to edit and update some text in React. I'm trying to use a prompt for this but I'm not sure if that is correct. Nothing is showing up when I console.log

this.state.newText
. Is there a better way to go about updating the text? I'm using tables in my HTML so using inputs in it causes an error. Thanks!

import React, { Component } from 'react';
import {IndexLink} from 'react-router';
import Item from '../styles/LinkItem.css';

class LinkItem extends Component {
constructor(props) {
super(props);
this.state = {
clicks: 0,
text: this.props.link,
newText: '',
editing: false
};
}
}
editLink() {
var newText = prompt('Update your link');
this.setState({
newText: newText,
editing: false
});
console.log(this.state.newText);
}
handleClick() {
const clicks = this.state.clicks;
this.setState({
clicks: clicks + 1
});
localStorage.setItem(`link-${this.props.link}`, JSON.stringify(clicks));
}
render() {
return (
<tr>
<td>
<IndexLink onClick={this.handleClick.bind(this)} to={{pathname: 'landing/' + this.props.link}}>{this.props.link}</IndexLink>
</td>
<td>{JSON.parse(localStorage.getItem(`link-${this.props.link}`))}</td>
<td><button className="btn btn-default" onClick={this.editLink.bind(this)}>Edit</button></td>
<td><button className="btn btn-danger" onClick={this.props.data.deleteLink.bind(null, this.props.index)}>Delete</button></td>
</tr>
);
}
}

export default LinkItem;

Answer

this.setState is async. Use a callback (a function that executes after the state is set) for console.log. That is the correct way. setState allows a callback. Right now it's printing nothing as it's printing the old value of newText which was set to the empty string in the constructor.

setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.

this.setState({
    newText: newText,
    editing: false
  },function(){
     console.log(this.state.newText);
  });