简体   繁体   中英

How to reload a component without refreshing the entire page?

Any help would be greatly appreciated, I've built out a simple quote generator project in React and would like the new quote to load without rendering the entire page. Currently, im using hooks and the quotes state resides in one component is it possible to reload/refresh state from another component using a click handler?

Project link: https://codesandbox.io/s/quote-generator-czffn?file=/src/components/buttons/Buttons.js

How it's currently reloading, using a refreshPage function. Thanks!

import React from 'react';

const Buttons = ({ quotes, getNewQuote }) => {
  const twitterUrl = `https://twitter.com/intent/tweet?text=${quotes.joke}`;
  //   console.log(twitterUrl);

  function refreshPage() {
    window.location.reload(false);
  }

  return (
    <div className='button-container'>
      <button
        onClick={() => window.open(twitterUrl, '_blank')}
        className='twitter-button'
        id='twitter'
        tittle='Tweet This!'
      >
        <i className='fab fa-twitter'></i>
      </button>
      <button id='new-quote' onClick={refreshPage}>
        New Quote
      </button>
    </div>
  );
};

export default Buttons;

If the quote is to show a new quote without refreshing the entire page, remove the axios request from the hook and put it in its own function.

  const getQuotes = () => {
    axios
      .get("https://geek-jokes.sameerkumar.website/api?format=json")
      .then(res => {
        setQuotes(res.data);
        // console.log(res.data);
      })
      .catch(err => console.log(err));
  }

// ...

<Buttons onClick={getQuotes} quotes={quotes} />

Then adjust the button to get use this function when it's clicked:

const Buttons = ({ quotes, getNewQuote, onClick }) => {

// ...

<button id="new-quote" onClick={onClick}>
  New Quote
</button>

You might want to add an animation while it's retrieving things as well with a useState for loading, but this should be a good start.

======= UPDATE =======

Here's also an example code to see how it could work. Click Run code snippet to see it working.

 const { useState, useEffect } = React; const Quote = props => { return <section> <blockquote> {JSON.stringify(props.quote)} </blockquote> <button onClick={props.onClick}>Get Quote</button> </section> } const App = () => { const [quotes, setQuotes] = useState(null); const [loading, setLoading] = useState(true); const getQuotes = () => { setLoading(true); axios.get("https://geek-jokes.sameerkumar.website/api?format=json").then(res => { if (res.data && res.data.joke) { setQuotes(res.data.joke); } setLoading(false); }).catch(err => { console.log(err); setLoading(false); }); } useEffect(() => { getQuotes(); }, []); return loading? <p>Loading...</p>: <Quote quote={quotes} onClick={getQuotes} /> } ReactDOM.render(<App />, document.querySelector('#root'));
 body { background: #efefef; font-family: Arial, sans-serif; padding: 20px; margin: 0; display: flex; justify-content: center; align-items: center; } section { background: white; border-radius: 6px; display: block; padding: 10px; } blockquote { padding: 10px; margin: 0 0 10px 0; border-bottom: 1px solid #efefef; font-size: 21px; } button { border-radius: 4px; background: blue; color: white; border: none; height: 40px; padding: 0 12px; font-size: 14px; } p { display: block; max-width: 80px; background: white; border-radius: 6px; padding: 20px; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/axios@0.19.2/dist/axios.min.js"></script> <div id="root"></div>

Codingwithmanny beat me to it.

Put the axios call in it's own function, and passdown the function to the button component.

Quote.js:

import React, { useState, useEffect } from "react";
import Buttons from "../buttons/Buttons";
import axios from "axios";

const Quote = () => {
  const [quotes, setQuotes] = useState("");

  const fetchQuotes = () => {
    axios
      .get("https://geek-jokes.sameerkumar.website/api?format=json")
      .then(res => {
        setQuotes(res.data);
        // console.log(res.data);
      })
      .catch(err => console.log(err));
  };
  useEffect(() => {
    console.log("new quote requested");
  }, [quotes]);

  return (
    <div className="quote-text">
      <i className="fas fa-quote-left" />
      <span id="quote"> {quotes.joke}</span>
      <Buttons quotes={quotes} getNewQuote={fetchQuotes} />
    </div>
  );
};

export default Quote;

Buttons.js

import React from "react";

const Buttons = ({ quotes, getNewQuote }) => {
  const twitterUrl = `https://twitter.com/intent/tweet?text=${quotes.joke}`;
  //   console.log(twitterUrl);

  return (
    <div className="button-container">
      <button
        onClick={() => window.open(twitterUrl, "_blank")}
        className="twitter-button"
        id="twitter"
        tittle="Tweet This!"
      >
        <i className="fab fa-twitter" />
      </button>
      <button id="new-quote" onClick={getNewQuote}>
        New Quote
      </button>
    </div>
  );
};

export default Buttons;

Codesandbox: https://codesandbox.io/s/quote-generator-heufm

You Should call New Qoute API on button click.

you button Component

import React from "react";

const Buttons = ({ quotes, getNewQuote }) => {
  const twitterUrl = `https://twitter.com/intent/tweet?text=${quotes.joke}`;
  //   console.log(twitterUrl);

  return (
    <div className="button-container">
      <button
        onClick={() => window.open(twitterUrl, "_blank")}
        className="twitter-button"
        id="twitter"
        tittle="Tweet This!"
      >
        <i className="fab fa-twitter" />
      </button>
      <button id="new-quote" onClick={getNewQuote}>
        New Quote
      </button>
    </div>
  );
};

export default Buttons;

Your Qoute component:

import React, { useState, useEffect } from "react";
import Buttons from "../buttons/Buttons";
import axios from "axios";

const Quote = () => {
  const [quotes, setQuotes] = useState("");
  useEffect(() => {
    axios
      .get("https://geek-jokes.sameerkumar.website/api?format=json")
      .then(res => {
        setQuotes(res.data);
        // console.log(res.data);
      })
      .catch(err => console.log(err));
  }, []);

  const getNewQuote = () => {
    axios
      .get("https://geek-jokes.sameerkumar.website/api?format=json")
      .then(res => {
        setQuotes(res.data);
        // console.log(res.data);
      })
      .catch(err => console.log(err));
  }

  return (
    <div className="quote-text">
      <i className="fas fa-quote-left" />
      <span id="quote"> {quotes.joke}</span>
      <Buttons quotes={quotes} getNewQuote={getNewQuote}/>
    </div>
  );
};

export default Quote;

You can do something like this.

In the Quote.js create getNewQuote function and call that function inside the useEffect .

Then, pass the getNewQuote function to the Button component and on New Quote button onClick set getNewQuote .

Here is your upgraded sandbox -> link

Quote.js

const Quote = () => {
  const [quotes, setQuotes] = useState("");
  useEffect(() => {
    getNewQuote();
  }, []);

  const getNewQuote = () => {
    axios
      .get("https://geek-jokes.sameerkumar.website/api?format=json")
      .then(res => {
        setQuotes(res.data);
        // console.log(res.data);
      })
      .catch(err => console.log(err));
  };

  return (
    <div className="quote-text">
      <i className="fas fa-quote-left" />
      <span id="quote"> {quotes.joke}</span>
      <Buttons getNewQuote={getNewQuote} quotes={quotes} /> // here you pass the getNewQuote function to the Buttons component
    </div>
  );
};

Buttons.js

const Buttons = ({ quotes, getNewQuote }) => {
  const twitterUrl = `https://twitter.com/intent/tweet?text=${quotes.joke}`;
  //   console.log(twitterUrl);

  return (
    <div className="button-container">
      <button
        onClick={() => window.open(twitterUrl, "_blank")}
        className="twitter-button"
        id="twitter"
        tittle="Tweet This!"
      >
        <i className="fab fa-twitter" />
      </button>
      <button id="new-quote" onClick={getNewQuote}> // here onClick you call the getNewQuote function
        New Quote
      </button>
    </div>
  );
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM