Получение ошибок React при обходе объекта JSON в области видимости с помощью точечной нотации [дубликат]

Когда вы пишете [x]*3, вы получаете, по существу, список [x, x, x]. То есть список с 3 ссылками на тот же x. Когда вы затем изменяете этот сингл x, он отображается через все три ссылки на него.

Чтобы исправить это, вам нужно убедиться, что вы создаете новый список в каждой позиции. Один из способов сделать это -

[[1]*4 for n in range(3)]

, который будет повторно оценивать [1]*4 каждый раз, а не оценивать его один раз и делать 3 ссылки на 1 список.


Вы можете удивиться почему * не может создавать независимые объекты так, как это делает понимание списка. Это потому, что оператор умножения * работает с объектами, не видя выражений. Когда вы используете * для умножения [[1] * 4] на 3, * видит только 1-элементный список [[1] * 4], а не текст выражения [[1] * 4. * не имеет понятия, как делать копии этого элемента, не знаю, как переоценить [[1] * 4], и не подозревайте, что вы даже хотите копировать, и вообще, возможно, даже не было способа скопировать элемент.

Единственный вариант * - это сделать новые ссылки на существующий подсписчик вместо того, чтобы пытаться создавать новые подсписки. Все остальное было бы непоследовательным или требовало бы значительного пересмотра основополагающих решений по языковому дизайну.

Напротив, понимание списка переоценивает выражение элемента на каждой итерации. [[1] * 4 for n in range(3)] пересчитывает [1] * 4 каждый раз по той же причине [x**2 for x in range(3)] каждый раз переоценивает x**2. Каждая оценка [1] * 4 генерирует новый список, поэтому понимание списка делает то, что вы хотели.

Кстати, [1] * 4 также не копирует элементы [1], но это не имеет значения , так как целые числа неизменны. Вы не можете сделать что-то вроде 1.value = 2 и превратить 1 в 2.

1
задан Avery Vann 24 March 2019 в 03:58
поделиться

3 ответа

Ошибка в первом теге p говорит вам, что именно происходит. Доступ к свойству «undefined» нарушит работу javascript / реагирует.

Вы, вероятно, не имеете ожидаемых данных в состоянии, чтобы проверить, что я говорю, просто отладьте с помощью console.log (this.state) в вашем рендере:

render() {
  console.log(this.state); // probably has this.state.recipes empty array at first render
  ...

this возможно, это произошло из-за того, что ваше состояние заполняется асинхронным вызовом API. Рендер будет вызван первым до того, как ваш асинхронный запрос от API будет разрешен (что означает, к сожалению, что у вас еще нет данных ..recipes [0] в вашем состоянии)

Я полагаю, у вас есть это в вашем componentDidMount:

componentDidMount() {
  ThirdParty.fetchRecipes().then(data => {
     this.setState({ recipes: data.recipes }); // after setState react calls render again. This time your p tag should work.
  })
  ...

Если у вас более новая версия реагирования, я бы рекомендовал использовать необязательную цепочку , потому что интересующее вас свойство глубоко вложено: Как обрабатывать вызовы функции для данных, которые могут быть неопределенными?

<p>{this.state?.recipes?.[0]?.title}</p>

Еще один эффективный способ, но слишком многословный:

const title =
  this.state &&
  this.state.recipes &&
  this.state.recipes.length &&
  this.state.recipes[0].title
    ? this.state.recipes[0].title
    : "";

render() {return (<p>{title}</p>)}
0
ответ дан Tyro Hunter 24 March 2019 в 03:58
поделиться

Я полагаю, что вы получаете JSON асинхронно. В этом случае вам следует рассмотреть граничные случаи, когда исходным состоянием рецептов является пустой массив.

  1. Когда вы запускаете первый тег p, поскольку JSON выбирается асинхронно, изначально this.state.recipes не определено, поэтому вы получаете ошибку.

  2. Когда вы запускаете второй тег p, во время первого рендеринга this.state.recipes не определен, следовательно, он работает внутри тега p, но после выборки JSON и установки состояния, рендер вызывается снова, и на этот раз this.state.recipes[0] является объектом, поэтому его нельзя считать действительным компонентом реакции, поэтому появляется ошибка.

  3. С 3-м тегом p, как вы упомянули сами, this.state.recipes.title успешно скомпилируется без ошибок, но значение будет неопределенным.

Вам просто нужно проверить крайние случаи, когда начальное состояние пусто.

        constructor(props) { 
            super(props);
            this.state = { recipes: [] }
        }

        render() {
             return (
                 <p>
                  {this.state.recipes.length > 0 ? {this.state.recipes[0].title} : ''}       
                </p> 
             )
         }
0
ответ дан Aaditya Thakkar 24 March 2019 в 03:58
поделиться

Вы можете сделать что-то подобное для обработки состояния, когда есть данные и когда нет данных.

0
ответ дан Jibin Mathews 24 March 2019 в 03:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: