1

So I have this application that displays random quotes that are pulled as JSON data from an API. It's my first foray into React so it is not really well done. Initially, I had all of my code stored in one component - but this was obviously not best practices because I had multiple things that could be split into components, i.e. a quote, a footer, a share button.

The issue I ran into when I split it up is that I didn't know how to share state between component files (for sharing to Twitter or other additional features) because I fetch the data like this:

/* this function accesses the API and returns a json */
export default function fetchQuote() {
    return fetch('https://programming-quotes-api.herokuapp.com/quotes/random') // fetch a response from the api
        .then((response) => { 
            let json = response.json(); // then assign the JSON'd response to a var
            return json; // return that bad boy
    });
}

which originally was called within the component class like so:

/* component for the quotes */
export default class Quote extends React.Component {
    /* placeholder */
    constructor(props) {
        super(props);
        this.state = {
            quoteAuthor: "Rick Osborne", 
            quote: "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."
        }
    }
    /* actually render things */
    render() {
        return (
            <div className="quotes">
                <h1>{this.state.quoteAuthor}</h1>
                <p>{this.state.quote}</p>
                <div className="button">
                    <button id="button" onClick={this.update}>New quote</button>
                </div>
            </div>
        );
    }

    /* async fetch the quotes and reassign the variables to them once processed */
    update = async() => {
        let response = await fetchQuote();
        console.log(response);
        this.setState({
            quoteAuthor: response.author,
            quote: response.en
        });
    };   
}

From my understanding, React's hooks seemed to solve my problem because I could use useState and useEffect which I tried to implement as follows (with the original fetchQuote() function untouched):

export default function Quote() {
    const [author, setAuthor] = useState("Rick Osborne");
    const [quote, setQuote] = useState(
        "Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live."
        );
    let json = fetchQuote();

    useEffect (() => {
        setAuthor(json.author);
        setQuote(json.quote);
        console.log(json);
    });

    return (
        <div className="quotes">
            <h1>{author}</h1>
            <p>{quote}</p>
            <div className="button">
                <button id="button" onClick={async () => json = await fetchQuote()}>
                    New quote
                </button>
            </div>
        </div>
    )
}

However, no errors are thrown except the area in which the quote is displayed shows empty and calling console.log(json) within the useEffect simply returns

Promise { <state>: "pending" }
Promise { <state>: "pending" }

Am I using Hooks properly? How can I properly update the state with the JSON data?

1 Answer 1

3

It looks like the promise from fetch isn't resolving. Try this:

export default Quote = () => {
    const [author, setAuthor] = useState("Rick Osborne");
    const [quote, setQuote] = useState('');

    const fetchMyAPI = async () => {
      let json = await fetchQuote();
      setAuthor(json.author);
      setQuote(json.quote);
    }

    useEffect(() => {
     fetchMyAPI();
    }, []);

    return (
        <div className="quotes">
            <h1>{author}</h1>
            <p>{quote}</p>
            <div className="button">
                <button id="button" onClick={fetchMyAPI}>
                    New quote
                </button>
            </div>
        </div>
    )

This called fetchMyAPI onMount, and calls it whenever you click on New Quote.

Sign up to request clarification or add additional context in comments.

Comments

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.