Nano Hash - криптовалюты, майнинг, программирование

Как предотвратить рендеринг компонента дочерним элементом до получения данных

У меня есть компонент Dashboard, который отображает массив карточек с данными, полученными с внутреннего сервера. Пользователи могут создавать дополнительные карточки, отправляя форму, которая затем перенаправляет их обратно на страницу панели инструментов.

Моя проблема заключается в том, что при отправке формы возникает ошибка javascript «невозможно прочитать свойство «включает» из неопределенного», и панель инструментов не отображается. Если я вручную обновлю страницу, список отобразится, как и ожидалось, с новой карточкой. Я использую метод Array.includes для фильтрации карт на основе значения состояния filterText. Эта ошибка возникает из-за того, что данные не были получены при вызове рендеринга? Если да, то как я могу заставить компонент ждать, пока не появятся данные перед рендерингом? Пожалуйста, смотрите компоненты и избыточное действие ниже.

const CardList = (props) =>  {

    const cards = props.cards.map(({ _id, title}) => {
            return (
                <Card key={_id} title={title} />
            )
        });

        return (
            <div className="container">
                <input onChange={ (e) => props.handleChange(e.target.value) } />
                <div className="row">
                    {cards}
                </div>
            </div>
        );
} 
export default CardList;

export class Dashboard extends Component {
    constructor(props) {
        super(props);
        this.state = {
            filterText: ''
        }
    }
    componentDidMount() {
        this.props.fetchCards();
    } 

    handleChange = (filterText) => {
        this.setState({filterText});
    }

    render() {
        const cardList = this.props.cards.filter(card => 
            card.title.includes(this.state.filterText.trim().toLowerCase())
        );
        return (
            <div>
                <CardList cards={cardList}
                    handleChange={filterText => this.handleChange(filterText)} />
            </div>
        );
    }
};
function mapStateToProps({ cards: { cards }}) {
    return {
        cards,
    }
}
export default connect(mapStateToProps, {fetchCards})(Dashboard);

export class SurveyForm extends Component {
render() {
        return (
            <div>
               <form>
                 <Field component={CardField} type="text" 
                     label={'title'} name={'title'} key={'title'} />
                 <Button type="submit" onClick={() => submitCard(formValues, history)}>Next</Button>
               </form>
            </div>
        );
    }
}
REDUX ACTION DISPATCHER:
export const submitCard = (values, history) => async dispatch => {
    const res = await axios.post('/api/cards', values);

    try {
        dispatch({ type: SUBMIT_CARD_SUCCESS, payload: res.data });
        dispatch({ type: FETCH_USER, payload: res.data })
    }
    catch(err) {
        dispatch({ type: SUBMIT_CARD_ERROR, error: err });
    }

    history.push('/cards');
}

Ответы:


1

Подобно тому, что упоминал @JasonWarta, стоит отметить, что React ничего не отображает, когда возвращаются false, null или undefined, поэтому обычно вы можете использовать &&, чтобы быть более кратким, чем использование условного («тройного») оператора:

render() {
  return this.props.cards && (
    <div>
      <CardList 
        cards={this.props.cards.filter(card => card.title.includes(this.state.filterText.trim().toLowerCase())}
        handleChange={filterText => this.handleChange(filterText)}
      />
    </div>
  );
}

Поскольку && замыкает, последняя часть не будет оцениваться, поэтому вы можете избежать TypeError, и компонент также не будет отображать содержимое (так же, как при возврате null).

17.05.2018
  • Мне очень понравился такой подход, если больше ничего рендерить не нужно. Спасибо, отметил :) 17.05.2018
  • Он также работает в сочетании с другим контентом. Если у компонента есть дочерний элемент со значением null/undefined/false, он также не будет отображаться. Это позволяет вам выполнять встроенные условные операторы в дереве. 17.05.2018
  • @Jacob спасибо, это имеет смысл. Однако это не работает, поэтому я думаю, что проблема в другом. Глядя на тип Error, он выбрасывается в последней строке действия приведения. history.push('/карты'). Это имеет значение? Я также могу отредактировать, чтобы опубликовать редуктор, если это поможет. 17.05.2018
  • Это становится немного нечитаемым, как только у нас есть еще пара условий, поэтому другой подход может состоять в том, чтобы выделить часть условия в отдельной функции. 17.05.2018

  • 2

    Я использовал тернарные операторы в такой ситуации. Возможно, вам придется настроить контрольную часть шаблона в зависимости от того, что возвращает ваш шаблон редукции. Значение null возвращается, если this.props.cards ложно.

    render() {
        return (
            {this.props.cards
                ?
                    <div>
                        <CardList 
                            cards={this.props.cards.filter(card => card.title.includes(this.state.filterText.trim().toLowerCase())}
                            handleChange={filterText => this.handleChange(filterText)}
                        >
                        </CardList>
                    </div>
                :
                    null
            }
        );
    }
    
    17.05.2018

    3

    В качестве альтернативы другим ответам вы можете вернуть что-то еще подходящее, если в вашей функции рендеринга нет данных с оператором if. Я предпочитаю перемещать функции, такие как ваш фильтр, за пределы рендеринга. Может быть, еще один (лучший?) подход делает этот фильтр в вашей функции mapStateToProps.

    Кроме того, если я не ошибаюсь, вам не нужно ничего передавать в функцию handleChange. Поскольку вы получаете filterText обратно из компонента CardList, а затем устанавливаете свое состояние.

    cardList = () => this.props.cards.filter(card => 
                card.title.includes(this.state.filterText.trim().toLowerCase()));
    
    render() {
     if ( !this.props.cards.length ) {
            return <p>No cards</p>
            // or return <SpinnerComponent />
        }
     return (
                <div>
                    <CardList cards={this.cardList()}
                        handleChange={this.handleChange} />
                </div>
            );       
     }
    
    17.05.2018
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..