I have two fetch
calls which updates the state. And I have two buttons. One makes a fetch call, another calls componentDidMount()
.
The first fetch call is in componentDidMount()
.
The second is On "All Time Sort" button click with handleSortRecent()
.
On "Recent Sort" button click, I want to show the previous informatin fetched in componentDidMount
. To achieve this
I am calling the componentDidMount()
method itself from handleSortRecent()
method.
Is there a better way to do this without using Redux
?
const API = "https://fcctop100.herokuapp.com/api/fccusers/top/";
class App extends Component {
constructor(props) {
super(props);
this.state = {
dataRecent : [],
dataAlltime : []
}
// This binding is necessary to make `this` work in the callback
this.handleClick = this.handleClick.bind(this);
this.handleSortRecent = this.handleSortRecent.bind(this);
}
componentDidMount() {
fetch(API+"recent")
.then( response => response.json() )
.then( data => this.setState( { dataRecent: data } ) );
}
handleClick () {
fetch(API+"alltime")
.then(response => response.json())
.then(data => this.setState({dataRecent:data}))
}
handleSortRecent() {
this.componentDidMount();
}
render() {
const arrRecentList = this.state.dataRecent;
return (
<div className="App">
<button onClick={this.handleClick}>All Time Sort</button>
<button onClick={this.handleSortRecent}>Recent Sort</button>
{
arrRecentList.map(data =>
<div key={data.username}>
<img src={data.img} width="50px" alt="" />
<a href={"https://www.freecodecamp.org/"+data.username} target="_blank">{data.username}</a>
<span> - </span>
<span>{data.recent}</span>
<span> - </span>
<span>{data.alltime}</span>
</div>
)
}
</div>
);
}
}
-
\$\begingroup\$ An SO question on saving previous state \$\endgroup\$radarbob– radarbob2018年02月05日 02:01:24 +00:00Commented Feb 5, 2018 at 2:01
1 Answer 1
It's strange that you would call this.componentDidMount
. I have not seen this before. Either way, what if you created an indicator in your state that declared what should be shown? For example:
this.state = {
dataRecent : [],
dataAlltime : [],
display: "recent"
}
Then inside of your render function you can choose what gets displayed.
this.state.display === 'recent'
? this.state.dataRecent.map...
: this.state.dataAlltime.map...
I would create two functions that handle getting both sets of data.
getAlltimeData() => {
fetch(API+"alltime")
.then(response => response.json())
.then(data => this.setState({ dataRecent:data }))
}
getRecentData() => {
fetch(API+"recent")
.then(response => response.json())
.then(data => this.setState({ dataRecent:data }))
}
You can then call both of them when the component mounts.
componentDidMount() {
this.getAlltimeData();
this.getRecentData();
}
At this point you have the data you need. What you don't have is a click handler to switch between recent and all time.
handleRecentClick() {
this.setState({ display: 'recent' });
}
handleAlltimeClick() {
this.setState({ display: 'allTime' });
}
Pass those to the buttons that change state respectively.
<button onClick={this.handleRecentClick}>All Time Sort</button>
<button onClick={this.handleAlltimeClick}>Recent Sort</button>
Make sure to bind your functions in the constructor like you did with the others.