0
\$\begingroup\$

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>
 );
 }
}

asked Feb 5, 2018 at 1:40
\$\endgroup\$
1

1 Answer 1

2
\$\begingroup\$

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.

answered Feb 17, 2018 at 6:13
\$\endgroup\$
0

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.