【问题标题】:How do I refresh a react component by clicking on a button outside the component?如何通过单击组件外部的按钮来刷新 React 组件?
【发布时间】:2021-08-18 13:56:45
【问题描述】:

我是 Web 开发的新手,因此决定学习 ReactJs。我正在尝试创建一个随机报价生成器作为 freecodecamp 前端库项目的一部分。问题:我有一个反应组件,它从网站获取报价,然后在屏幕上显示一个随机报价。我在组件之外还有一个按钮,其唯一目的是获取新代码并将其显示在屏幕上。每当我单击按钮时,如何刷新反应组件?任何帮助表示赞赏!:D 这是我的组件:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      quote: ''
    };
  }

  componentDidMount() {
    fetch("https://type.fit/api/quotes")
      .then(res => res.json())
      .then(
        (result) => {
          this.setState({
            quote: result[Math.floor(Math.random() * result.length)]
          });
        },
      )
  }


  render() {
    return ( 
      <p id = 'reactQuote'>{this.state.quote.text}< /p>
    );
  }
}

ReactDOM.render( MyComponent />, document.getElementById('text'))
<div id="text"></div>
<button id='new-quote'>New Quote</button>

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    当组件的状态发生变化时,组件会自动刷新,但按钮和文本应该是组件本身(或组件的子组件)的一部分。一个示例(使用单个组件)是:

    // your component
    class RandomQuoteMachine extends React.Component {
      constructor() {
        super();
        this.state = {
          quotes: [], // here you store an array of quote objects
          currentQuote: null // here you store the quote object that is currently displayed
        };
        this.getRandomQuote = this.getRandomQuote.bind(this)
      }
    
      // when the component mounts, fetch the quotes from the API
      componentDidMount() {
        fetch("https://type.fit/api/quotes") // fetch the entire list of quotes from the API
          .then(response => response.json()) // turn the response into a Javascript object
          .then(result => {
            // update the state
            this.setState({
              quotes: result,
              currentQuote: result[Math.floor(Math.random() * result.length)] || null
            });
          });
      }
    
      getRandomQuote() {
        // randomly select a quote from the state
        const newQuote = this.state.quotes[Math.floor(Math.random() * this.state.quotes.length)] || null;
        // update the state with the new current quote
        this.setState({
          currentQuote: newQuote
        });
      }
    
      render() {
        return (
          <div>
            <blockquote>{ this.state.currentQuote && this.state.currentQuote.text || '' }</blockquote>
            <p className = "author">{ this.state.currentQuote && this.state.currentQuote.author || 'unknown' }</p>
            <button onClick = { () => this.getRandomQuote() }>get a new quote from the list</button>
          </div>
        );
      }
    }
    
    // mounting the component in the page
    ReactDOM.render( < RandomQuoteMachine / > , document.getElementById('app'))
    /* A bit of styling, just for presentation sake */
    
    * {
      font-family: sans-serif;
    }
    
    blockquote {
      font-size: 2rem;
      font-style: italic;
      margin: 0;
      padding: 0.5rem 0.5rem 0.5rem 3rem;
      border-left: 3px solid #ccc;
    }
    
    .author {
      font-size: 1.2rem;
      padding-right: 0.5rem;
      text-align: right;
    }
    
    .author::before {
      content: "(";
    }
    
    .author::after {
      content: ")";
    }
    <!-- Importing React and ReactDOM -->
    <script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
    
    <!-- This is where your component will be mounted -->
    <div id="app">
    
    </div>

    或者,如果您更喜欢功能组件和钩子:

    const RandomQuoteMachine = () => {
      const [quotes, setQuotes] = React.useState([]);
      const [currentQuote, setCurrentQuote] = React.useState(null);
    
      React.useEffect(() => {
        fetch("https://type.fit/api/quotes")
          .then(response => response.json())
          .then(result => {
            setQuotes(result);
            setCurrentQuote(result[Math.floor(Math.random() * result.length)] || null);
          })
      }, [setQuotes, setCurrentQuote]);
    
      const getRandomQuote = React.useCallback(() => {
        const newQuote = quotes[Math.floor(Math.random() * quotes.length)] || null;
        setCurrentQuote(newQuote)
      }, [quotes, setCurrentQuote]);
    
      return (
        <div>
          <blockquote> { currentQuote && currentQuote.text || '' } </blockquote>
          <p className = "author"> { currentQuote && currentQuote.author || 'unknown' }</p>
          <button onClick = { () => getRandomQuote() }> get a new quote from the list </button>
        </div>
      );
    }
    
    ReactDOM.render(<RandomQuoteMachine />, document.getElementById('app'));
    * {
      font-family: sans-serif;
    }
    
    blockquote {
      font-size: 2rem;
      font-style: italic;
    }
    
    .author {
      font-size: 1rem;
      text-align: right;
    }
    
    .author::before {
      content: "(";
    }
    
    .author::after {
      content: ")";
    }
    <script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
    
    <div id="app">
    
    </div>

    【讨论】:

    • 由于我设计应用程序的方式,包括组件中的按钮会弄乱一些弹性框。我使用了您的方法并向按钮添加了“显示:无”,以便它不会显示,然后使用 JQuery 将外部按钮绑定到 React 组件中的按钮。下次我设计 React 应用程序时会注意您的解决方案:)
    • "由于我设计应用程序的方式..." 这可能表明设计本身存在问题;无论如何,你不应该只需要使用 jQuery 来将某些东西“绑定”到 DOM 元素(当你需要与 DOM 交互时,React 有 Refs)并且如果问题只是链接到按钮在内部或外部同样div,您可以将按钮放在 div 之外并使用Fragment 来包装所有内容。你可以在这里看到一个例子:jsfiddle.net/8o4fczgq
    【解决方案2】:

    创建一个组件来封装按钮和您的组件,将引号作为上层组件的状态并将其作为道具传递给您的组件,现在当您按下按钮时,它将改变上层组件中的状态它将被传递给您的组件,强制它刷新并显示新报价。

    【讨论】:

      【解决方案3】:

      您可以在单击按钮时调用按钮上的函数。该功能可以作为道具传递给您的按钮组件。

      function fetchData(){
           fetch("https://type.fit/api/quotes")
              .then(res => res.json())
              .then(
                (result) => {
                  this.setState({
                    quote: result[Math.floor(Math.random() * result.length)]
                });
              },
            )
      }
      
      <button id='new-quote' onClick={fetchData}>New Quote</button>
      

      【讨论】:

      • 这种方法会获取所有引号,以便在每次单击按钮时显示一个;更好的方法是在组件挂载时获取引号并将它们存储在状态中,然后从状态中随机选择一个引号
      猜你喜欢
      • 2020-06-06
      • 1970-01-01
      • 2018-09-27
      • 2021-12-25
      • 1970-01-01
      • 2019-11-11
      • 2021-02-08
      • 1970-01-01
      • 2018-09-11
      相关资源
      最近更新 更多