10

Im working on a ReactJS project where you can generate a random activity when pressing the generate button. Im doing a fetch to my api to display some data from it. This works fine. Now I want to do the fetch and display the returned data every time I click the generate button (which is in the home component). So the generate button has to do a new fetch and refresh the component. Also it has to be empty on default. I searched a while and can't find a relevant answer. Can some of you guys help me out? Thanks.

fetch component

import React from "react";

export class ItemLister extends React.Component {
    constructor() {
        super();
        this.state = { suggestion: "" };
    }

    componentDidMount() {
        fetch("......./suggestions/random", {
            method: "GET",
            dataType: "JSON",
            headers: {
                "Content-Type": "application/json; charset=utf-8"
            }
        })
            .then(resp => {
                return resp.json();
            })
            .then(data => {
                this.setState({ suggestion: data.suggestion });
            })
            .catch(error => {
                console.log(error, "catch the hoop");
            });
    }

    render() {
        return <h2>{this.state.suggestion}</h2>;
    }
}

home component

import React from "react";
import { ItemLister } from "./apiCall";

export class Home extends React.Component {
    constructor(props) {
        super(props);
        console.log();
        window.sessionStorage.setItem("name", this.props.params.name);
        window.sessionStorage.setItem("token", this.props.params.token);
    }

    render() {
        return (
            <div className="contentContainer AD">
                <table>
                    <thead>
                        <tr>
                            <th>
                                <p>Het is heel leuk als het werkt!</p>
                            </th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>
                                <ItemLister />
                            </td>
                        </tr>
                    </tbody>
                </table>
                <div className="container center">
                    <button>GENERATE</button>
                    <button>SAVE</button>
                    <button>MATCH</button>
                </div>
            </div>
        );
    }
}
4
  • Are you still facing any issues with rendering suggestion? Commented Oct 5, 2017 at 13:31
  • 1
    No not with rendering. The main issue is setting an onClick in the generate button to connect the fetch function. Commented Oct 5, 2017 at 13:36
  • You want to refresh ItemListener component every time by clicking generate button. Correct? Commented Oct 5, 2017 at 14:06
  • That is correct Commented Oct 5, 2017 at 14:11

2 Answers 2

10

I would say that you move your fetch logic to home component and maintain a state in home component just like you are doing in Itemlister component. Then all you have to do is pass your state to Itemlister component. Your home component will look like this

export class Home extends React.Component {
constructor(props) {
    super(props)
    this.state = {suggestion: ""}
    ...
}

componentDidMount(){
  // For initial data
  this.fetchData();
}

fetchData = () => {
  fetch("......./suggestions/random", {
    method: "GET",
    dataType: "JSON",
    headers: {
      "Content-Type": "application/json; charset=utf-8",
    }
  })
  .then((resp) => {
    return resp.json()
  }) 
  .then((data) => {
    this.setState({ suggestion: data.suggestion })                    
  })
  .catch((error) => {
    console.log(error, "catch the hoop")
  })
}

render() {
    return (
        ...
                <tbody >
                   // Pass state to itemlister like this
                    <tr><td><ItemLister suggestion={this.state.suggestion}/></td></tr>
                </tbody>
            </table>
            <div className="container center">
                // Add event handler here. On every click it will fetch new data
                <button onClick={this.fetchData}>GENERATE</button>
                <button>SAVE</button>
                <button>MATCH</button>
            </div>
        </div>
    )
  }
}

And your ItemLister component has the responsibility to display the data via props.

export class ItemLister extends React.Component {
    constructor() {
    super();
    }

    render() {
    return(
      <h2> 
        {this.props.suggestion}
      </h2>
      )
     }
    } 

As per the suggestion by dubes in comment, If you don't want to maintain any state in this component then you can make this functional component like this

function ItemLister(props) {
  return <h2> 
            {props.suggestion}
          </h2>;
}
Sign up to request clarification or add additional context in comments.

4 Comments

This is a much cleaner approach (and recommended one as well as per my understanding). One suggestion: the ItemListener component can be a functional component
This works great however, it isn't empty on default. It does a fetch when the page loads so there's already data before the user pressed generate.
@StevenvanEck If you want it empty by default then just remove this.fetchData(); line from componentDidMount function.
But, fetching the data before being asked for, wouldn't risk to fetch potentially too much data and risk perfomance and memory consumption?
2

I am not quite sure if I understood you correctly... but since you're adding your fetch inside a react extended class, you can render it inside the home component like so:

  state = {
    visible: false
  }

  generateItem() {
    if (this.state.visible) {
      return <ItemLister />
    }
    return <h2>nothing to show</h2>
  }

  render() {
    return(
      <div>
        <button onClick={() => this.setState({visible: true})}>Click</button>
        {this.generate()}
      </div>
    )
  }

The onClick function will update the state every time the user clicks on it and a new rerender will occur thus calling generateItem again with a new random word.

Hope this is what you were searching for.

2 Comments

Thank you, this helped me a lot however I need to do the fetch every time the button is clicked. Now it will only fetch the first time clicked.
It should call the fetch again once you click on the button again

Your Answer

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.