admin管理员组

文章数量:1287548

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 ponent is it possible to reload/refresh state from another ponent using a click handler?

Project link: =/src/ponents/buttons/Buttons.js

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

import React from 'react';

const Buttons = ({ quotes, getNewQuote }) => {
  const twitterUrl = `=${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;

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 ponent is it possible to reload/refresh state from another ponent using a click handler?

Project link: https://codesandbox.io/s/quote-generator-czffn?file=/src/ponents/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./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;
Share Improve this question asked Jul 24, 2020 at 12:53 cpadillacpadilla 671 gold badge1 silver badge6 bronze badges 1
  • Updated my answer to include an example if that helps. – codingwithmanny Commented Jul 24, 2020 at 13:25
Add a ment  | 

5 Answers 5

Reset to default 4

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./ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://unpkg./[email protected]/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 ponent.

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./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./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 ponent:

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 ponent 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 ponent
    </div>
  );
};

Buttons.js

const Buttons = ({ quotes, getNewQuote }) => {
  const twitterUrl = `https://twitter./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>
  );
};

React provides the key attribute pass to the element. We can reload the page in the React environment using a key attribute by doing a hard refresh which is a bit odd practice in terms of the React ecosystem. So whenever the key attribute changes the react diffing algo es in mid and then it first unmounts the previous ponent as the key is changed and then loads the ponent on DOM again please don't confuse it with reload it was first to render as the key is changed of the Children.

Example: I have the user logged in to the site and can update the token(with some other user profile) even user is still logged in.

Code:

import React, { useEffect, useState, Fragment } from "react";
import axios from "axios";

const TokenComponent = ({ children }) => {
  const [token, setToken] = useState(null);

  const fetchToken = async () => {
    try {
      const response = await axios.get("/api/token"); 
      const fetchedToken = response.data.token; 
      setToken(fetchedToken);
    } catch (error) {
      console.error("Error fetching token:", error);
    }
  };

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

  if (!token) {
    return <p>Loading token...</p>; 
  }

  return <Fragment key={token}>{children}</Fragment>;
};

export default TokenComponent;

You can see now whenever the token updates the react cannot find the ponent associated with the previous key(token) in nodes so the ponent associated with the previous key will first unmount and the ponent with the updated key will load(don't mix this with reload) on the DOM.

本文标签: javascriptHow to reload a component without refreshing the entire pageStack Overflow