React - prop-types отмечены как обязательные

У меня возникает ошибка, когда я использую propTypes и дочерние элементы условного рендеринга.

Ошибка: Warning: Failed prop type: The prop 'rate' is marked as required in 'Rate', but its value is 'undefined'

// index.js
import React, { Component } from "react";
import { render } from "react-dom";
import Rate from "./components/Rate";
import Card from "./components/Card";

class App extends Component {
  state = {
    loading: true
  };

  componentDidMount() {
    setTimeout(() => this.setState({ loading: false, rate: 5 }), 5000);
  }

  render() {
    return (
      <Card loading = {this.state.loading}>
        <Rate rate = {this.state.rate} />
      </Card>
    );
  }
}

render(<App />, document.getElementById("root"));

// rate.js
import React from "react";
import PropTypes from "prop-types";

const Rate = ({ rate }) => (
  <div>
    <span>{rate}/10</span>
  </div>
);

Rate.propTypes = {
  rate: PropTypes.number.isRequired
};

export default Rate;

Я воспроизвел здесь свою ошибку: https://codesandbox.io/embed/qvx8q78ypw

Я хочу отображать дочерний элемент, только если для загрузки установлено значение false. Обновлено: я не понимаю, почему я получаю эту ошибку в компоненте Rate, пока она не будет отображена
Я не понимаю, почему я получаю эту ошибку.

Спасибо за помощь

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
1 506
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы пытаетесь загрузить компонент <Rate /> с опорой rate, равной this.state.rate в <App />. В состоянии вашего компонента приложения ничего не установлено для this.state.rate, поэтому, хотя <Rate /> ожидает PropTypes.Number, на самом деле он получает undefined. Вот почему он жалуется.

Чтобы решить эту проблему, вы можете установить состояние для <App /> примерно так:

state = {
  loading: true
  rate: 0,
};

Спасибо за ответ, но в моем реальном приложении я использую redux, а значение rate равно undefined, а через несколько секунд я получаю значение. Так что я могу установить rate: 0 в моем состоянии

Joris 10.06.2018 00:40

@mdck, если это undefined, а ваш компонент ожидает rate: PropTypes.number.isRequired, вам будет плохо.

imjared 10.06.2018 00:41

Да, но я использую условное выражение для рендеринга потомков или нет, почему PropTypes выполняются, если для загрузки установлено значение true?

Joris 10.06.2018 00:45
Ответ принят как подходящий

На данный момент вы можете использовать значение свойства по умолчанию:

Rate.defaultProps = {
  rate: 0
};

Вы не делаете Карту условно, как сказал @Cody Moniz в ответе. Вы всегда это делаете. Вероятно, что в компоненте Card вы что-то скрываете или показываете, это зависит от свойства загрузки, которое вы ему передали. Не беспокойтесь об этом, просто используйте условный рендеринг должным образом и, возможно, немного очистите свой компонент Card.

render() {
    return !this.state.loading && (
      <Card>
        <Rate rate = {this.state.rate} />
      </Card>
    );
}

Здесь, если React получает значение null или false, он ничего не отображает. Итак, когда ваше состояние загрузки - false, вы ничего не визуализируете, после того, как оно изменится на true, вторая часть оценивает и отображает ваш компонент. Вторая часть не оценивается до тех пор, пока первая не станет истинной с помощью логического оператора &&. Это хороший и чистый способ сделать условный рендеринг, особенно если вы не хотите ничего показывать в первом условии.

Если вы хотите показать что-то о Card (то есть визуализировать его), но только условно визуализировать компонент Rate, вы можете применить эту логику в своем компоненте Card с загрузочной опорой, которую получает ваш компонент Card.

Это может работать, но я не понимаю, почему я получаю эту ошибку в компоненте Rate, пока она не будет отображена.

Joris 10.06.2018 01:32

Хорошо, я отредактировал свой ответ и немного расширил его, что сказал @Cody Moniz.

devserkan 10.06.2018 03:54

<Rate> все еще обрабатывается в <App>, единственное, что делает <Card>, - это скрывает или показывает уже отрендеренные элементы this.props.children, переданные ему.

Другие вопросы по теме