更改为React State不会更新功能组件中的显示

时间:2018-12-05 08:28:51

标签: javascript reactjs

我创建了一个简单的2组件应用程序,其中动物的名字显示了动物的图标,以概括我在更复杂的应用程序中遇到的问题。

一旦选择了随机动物并将其合并到state中,Display组件应重新渲染,animalIcon也应更新,因为state正在通过向下穿过props(或者我认为如此)。

相反,我们被困在任何第一个动物(随机选择)的图标上。

我真的很想知道为什么图标不更新,因为我认为更改state时,它将重新呈现使用该信息的组件(在这种情况下,{{ 1}}组件),而Display正确地向我展示了在console.log(animalIcon)组件的每次重新渲染中,Display都被正确分配了正确的元素/图标。

唯一不变的是animalIcon组件的{animalIcon}语句中return的输出。

Display
class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentAnimal: ''
    }
    this.getAnimal = this.getAnimal.bind(this);
  }
  
  getAnimal() {
    
    function getRandomAnimal(arr) {
      function getRandomIndex(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
      }
      
      return arr[getRandomIndex(0, arr.length - 1)];
    }
    
      const allAnimals = ['cat', 'dog', 'mouse'];
      const chosenAnimal = getRandomAnimal(allAnimals);
      this.setState({currentAnimal: chosenAnimal});
  }
  
  render() {
    return(
      <Display getAnimal={this.getAnimal} animal={this.state.currentAnimal}/>
    )
  }
}

function Display (props) {
  const icons = {
    cat: <i class="fas fa-cat"></i>,
    dog: <i class="fas fa-dog"></i>,
    mouse: <i class="fas fa-mouse-pointer"></i>,
  }
  
  let animalIcon = icons[props.animal.toLowerCase()];
  console.log(animalIcon);
  
  return (
    <div>
      <h1>{props.animal} looks like {animalIcon}</h1>
      <button onClick={props.getAnimal}>Get New Animal</button>
    </div>
  )
}

ReactDOM.render(<App />, document.querySelector('.root'));

2 个答案:

答案 0 :(得分:1)

您可以使用属性key包装animalIcon,因为您传递道具时,它似乎无法正确更新。如果动物名称更改,这将告诉反应以更新图标。

<span key={props.animal}>{
      animalIcon
    }</span>

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentAnimal: ''
    }
    this.getAnimal = this.getAnimal.bind(this);
  }

  getAnimal() {

    function getRandomAnimal(arr) {
      function getRandomIndex(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min;
      }

      return arr[getRandomIndex(0, arr.length - 1)];
    }

    const allAnimals = ['cat', 'dog', 'mouse'];
    const chosenAnimal = getRandomAnimal(allAnimals);
    this.setState({
      currentAnimal: chosenAnimal
    });
  }

  render() {
    return ( <
      Display getAnimal = {
        this.getAnimal
      }
      animal = {
        this.state.currentAnimal
      }
      />
    )
  }
}

function Display(props) {
  const icons = {
    cat: < i class = "fas fa-cat" > < /i>,
    dog: < i class = "fas fa-dog" > < /i>,
    mouse: < i class = "fas fa-mouse-pointer" > < /i>,
  }

  let animalIcon = icons[props.animal.toLowerCase()];
  console.log(props.animal);

  return ( <div ><h1> {
      props.animal
    }
    looks like <span key={props.animal}>{
      animalIcon
    }</span> < /h1> <
    button onClick = {
      props.getAnimal
    } > Get New Animal < /button> <
    /div>
  )
}

ReactDOM.render( < App / > , document.querySelector('.root'));
<script src="https://use.fontawesome.com/releases/v5.5.0/js/all.js"></script>
<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 class="root"></div>

答案 1 :(得分:-1)

在组件显示中,animalIcon应该是一个函数。

let animalIcon = () => icons[props.animal.toLowerCase()];

然后,使用相同组件的return()方法。

<h1>{props.animal} looks like {animalIcon()}</h1>

出于惯例,您可能需要将animcalIcon更改为getAnimalIcon

发生的事情是,在Class组件中,您的代码在render()生命周期内可以正常工作,该生命周期将重新评估与每个渲染中当前更改有关的所有内容,但是,在此过程中组件,它是一个函数,将发生的事情是,return()仅会被触发,因此,它将在组件收到新动物时返回animalIcon的第一个值而不会更改它,因为您没有告诉它应该更改。