Изменение в состояние реакции не обновляет отображение в функциональном компоненте - PullRequest
0 голосов
/ 05 декабря 2018

Я создал простое двухкомпонентное приложение, в котором имя животного отображает значок животного, чтобы обобщить проблему, с которой я столкнулся в более сложном приложении.

После выбора и объединения случайного животногов state компонент Display должен перерисоваться, и animalIcon также должен обновиться, поскольку state передается через props (или так я думал).

Вместо этого мы застряли на иконке того, кем является первое животное (выбранное случайным образом).

Мне бы очень хотелось узнать, почему значок не обновляется, поскольку я думал, что при изменении state он будет перерисовывать компоненты, которые используют эту часть информации (в данном случае, 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'));
<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>

Ответы [ 2 ]

0 голосов
/ 05 декабря 2018

Вы можете обернуть 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>
0 голосов
/ 05 декабря 2018

на дисплее вашего компонента animalIcon должен быть функцией.

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

затем, в return() методе того же компонента.

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

для соглашения, вы можете изменить animcalIcon на getAnimalIcon.

, так как в компоненте Class ваш код будет работать нормально в жизненном цикле render(), который переоценивает все, что связано с текущим изменением в каждом и каждом рендере, но в этом компоненте, который является функцией, произойдет только то, что return() только будет запущен, таким образом, он вернетпервое значение animalIcon без изменения, когда компонент получает новое животное, потому что вы не сказали ему, что оно должно быть изменено.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...