【问题标题】:React.js how to render random image changing state?React.js如何渲染随机图像变化状态?
【发布时间】:2021-02-06 17:13:43
【问题描述】:

我正在尝试制作一个简单的游戏:国家/地区的国旗在屏幕上一一闪烁,并在单击按钮后停在一个特定的国旗上。

这是我目前所拥有的:

import React from 'react'
import ReactDOM from 'react-dom'


// CSS styles in JavaScript Object
const buttonStyles = {
  backgroundColor: '#61dbfb',
  padding: 10,
  border: 'none',
  borderRadius: 5,
  margin: 30,
  cursor: 'pointer',
  fontSize: 18,
  color: 'white',

}
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { image: 'https://www.countryflags.io/US/shiny/64.png' }
    this.makeTimer()
  }

  makeTimer() {
    setInterval(() => {
      let countries = {
        USA: 'https://www.countryflags.io/US/shiny/64.png',
        Australia: 'https://www.countryflags.io/AU/shiny/64.png',
        "Puerto Rico": 'https://www.countryflags.io/PR/shiny/64.png'
      }
      let currentCountry = Math.floor(Math.random() * (Object.entries(countries).map(([key, value]) => <div>{key} <img alt={key} src={value}></img></div>)))
      this.setState({ currentCountry })
    }, 1000)
  }

  stopInterval = () => {
    clearInterval(this.interval);
  }
  render() {

    return (
      <div className='app'>
        <h1>where are you going on vacation?</h1>

        <div>{this.state.currentCountry}</div>
        <button style={buttonStyles} onClick={this.stopInterval}> choose country </button>

      </div>
    )
  }
}
const rootElement = document.getElementById('root')
ReactDOM.render(<App />, rootElement)

它不起作用,渲染的只是:

NaN

在我添加Math.floor(Math.random() * ...) 之前,它同时渲染了所有三个标志,这不是我想要的。哪里错了?

另外,我不确定计时器是否正常工作。

【问题讨论】:

  • 没有阅读所有内容,但Math.floor(Math.random()) 始终为零。

标签: javascript reactjs


【解决方案1】:

您不能将数字 (Math.random) 与数组 (Object.entries(countries).map) 相乘。

如果要将标志存储在对象中,则应创建一个辅助函数以从对象中获取单个元素(或值)。

此外,您永远不应该在您的状态中存储 JSX 元素。您所需要的只是一个 URL,而不是整个图像元素。如果状态更新,您可以存储一个随机 URL 并更新图像的src

const buttonStyles = {
  backgroundColor: '#61dbfb',
  border: 'none',
  borderRadius: 5,
  color: 'white',
  cursor: 'pointer',
  fontSize: 18,
  margin: 30,
  padding: 10,
};

function randomProperty(obj) {
  const keys = Object.keys(obj);
  return obj[keys[(keys.length * Math.random()) << 0]];
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentCountry: null,
      image: 'https://flagcdn.com/w128/us.png',
    };
    this.makeTimer();
  }

  makeTimer() {
    let countries = {
      'Australia': 'https://flagcdn.com/w160/au.png',
      'Puerto Rico': 'https://flagcdn.com/w160/pr.png',
      'USA': 'https://flagcdn.com/w160/us.png',
    };

    this.interval = setInterval(() => {
      let currentCountry = randomProperty(countries);
      this.setState({ currentCountry });
    }, 1000);
  }

  stopInterval = () => {
    clearInterval(this.interval);
  };

  render() {
    return (
      <div className="app">
        <h1>Where are you going on vacation?</h1>
        <img alt="" src={this.state.currentCountry} width="80" />
        <button style={buttonStyles} onClick={this.stopInterval}>
          Choose country
        </button>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

【讨论】:

    【解决方案2】:

    我为你准备了一些不同的东西,我希望它对你有所帮助。

    let countries = {
        USA: 'https://www.countryflags.io/US/shiny/64.png',
        Australia: 'https://www.countryflags.io/AU/shiny/64.png',
        'Puerto Rico': 'https://www.countryflags.io/PR/shiny/64.png',
    };
    
    //I changed the object to array for better data manipulation.
    const countriesArray = Object.entries(countries).map(country => {
        return { name: country[0], flag: country[1] }
    })
    
    //Getting random country index by its length
    const randomCountryIndex = Math.floor(Math.random() * countriesArray.length);
    
    console.log("Set the current country: ", countriesArray[randomCountryIndex])
    console.log("Set the random flag: ", countriesArray[randomCountryIndex].flag)

    因此,在此之后,您可以检查用户的答案是否与 state 上的当前国家/地区相匹配

    【讨论】:

      【解决方案3】:

      避免 jsx 处于状态。 重构了您的 Math.random() 代码。

      import React from 'react'
      import ReactDOM from 'react-dom'
      
      
      const countries = [
          { name: "USA", image: 'https://www.countryflags.io/US/shiny/64.png' },
          { name: "Australia", image: 'https://www.countryflags.io/AU/shiny/64.png'},
          { name: "Puerto Rico", image: 'https://www.countryflags.io/PR/shiny/64.png' }
      ];
      // CSS styles in JavaScript Object
      const buttonStyles = {
          backgroundColor: '#61dbfb',
          padding: 10,
          border: 'none',
          borderRadius: 5,
          margin: 30,
          cursor: 'pointer',
          fontSize: 18,
          color: 'white',
      
      }
      class App extends React.Component {
          constructor(props) {
              super(props);
              this.state = { image: 'https://www.countryflags.io/US/shiny/64.png' }
              this.makeTimer()
          }
      
          makeTimer() {
              this.interval = setInterval(() => {
                  const countryIndex = Math.floor(Math.random() * countries.length);
                  this.setState({
                      image: countries[countryIndex].image
                  });
              }, 1000)
          }
      
          stopInterval = () => {
              clearInterval(this.interval);
          }
          render() {
      
              return (
                  <div className='app'>
                      <h1>where are you going on vacation?</h1>
      
                      <div>{this.state.currentCountry}</div>
                      <button style={buttonStyles} onClick={this.stopInterval}> choose country </button>
      
                  </div>
              )
          }
      }
      const rootElement = document.getElementById('root')
      ReactDOM.render(<App />, rootElement)
      

      【讨论】:

        【解决方案4】:

        Math.floor(Math.random()) 返回零! 使用这个:

        Math.floor(Math.random() * 10);
        

        【讨论】:

        • OP 在他们的代码中没有使用Math.floor(Math.random()),而是Math.floor(Math.random() * somevalue);,这正是您的建议。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-10-27
        • 1970-01-01
        • 1970-01-01
        • 2021-02-22
        • 2020-08-20
        • 2014-12-11
        相关资源
        最近更新 更多