Передайте данные выборки компонентам, используя useState React Native

Я новичок в React Native. На самом деле это мое первое приложение.

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

Это мой App.js

import React, {useState, useEffect} from 'react';
import { View, StyleSheet, ScrollView } from 'react-native';

import Header from './parts/header';
// import BigNews from './parts/big-news';
import Index from './screens/index.js';

const authorization = { authorization: '1234aa' };

export default function App() {
  const [fetchApiData, setApiData] = useState();

  useEffect(() =>
  fetch('https://example.com/get-app-home.php', {
    method: 'POST', // or 'PUT'
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(authorization),
  })
  .then(res => res.json())
  .then(res => {
    this.setState({ setApiData: res })
  })
  .catch(() => this.setState({ hasErrors: true }))
  );
  return (
    <View style={styles.viewport}>
      <Header />
      <ScrollView style={styles.contentHolder}>
        <Index content={fetchApiData}/>
      </ScrollView>
    </View>
);


}

А это мой файл index.js

import React from 'react';
import { View, Text } from 'react-native';

import BigNews from '../parts/big-news';
import SmallNews from '../parts/small-news';
import Colors from '../constants/colors'

const Index = props => {

    return (
      <View>
        <BigNews
        image={props.content.first.image}
        pretitle={props.content.first.pretitle}
        title={props.content.first.title}
        introduction={props.content.first.introduction}
        style={{color: props.content.first.mark}}/>

        <SmallNews
        image={props.content.second.image}
        pretitle={props.content.second.pretitle}
        title={props.content.second.title}
        style={{color: props.content.first.mark}}/>

        <SmallNews
        image={props.content.second.image}
        pretitle={props.content.second.pretitle}
        title={props.content.second.title}
        style={{color: props.content.first.mark}}/>

        <SmallNews
        image={props.content.second.image}
        pretitle={props.content.second.pretitle}
        title={props.content.second.title}
        style={{color: props.content.first.mark}}/>
      </View>
    );
}
export default Index;

Я постоянно получаю TypeError: undefined не является объектом (оценка 'props.content.first')

Я пробовал миллион способов, но в большинстве случаев это ошибка, которую я вижу. Если я делаю console.log состояния, я получаю либо неопределенное, либо пустое.


person Korovjov    schedule 17.02.2020    source источник


Ответы (2)


В вашем компоненте Index свойство content изначально не определено, поскольку вы не передаете никакого значения (часто называемого "начальным состоянием") функции useState в вашем компоненте App.

Вместо этого попробуйте:

const [ fetchApiData, setApiData ] = useState({
    first: {},
    second: {}
});

Обратите внимание, что я заполнил начальное состояние элементами first и second, потому что попытка доступа к элементам, расположенным ниже по дереву (image, pretitle и т. д.), все равно вызовет ошибку.

person George    schedule 17.02.2020
comment
Хорошо, вы решили одну проблему. Теперь я получил ошибку: TypeError: уничтожение не является функцией (в уничтожении () уничтожение является экземпляром Promise) - person Korovjov; 18.02.2020
comment
@Korovjov Звучит как повод для другого вопроса. Быть конкретной. - person George; 18.02.2020
comment
Это конкретное дело. Это ошибка. Больше ничего. ibb.co/YN5F4x3 - person Korovjov; 18.02.2020
comment
Хорошо, я понял, проблема была с асинхронным ожиданием в Fetch API. Мне пришлось создать асинхронную функцию. Могу ли я каким-либо образом добиться этого (вы предложили первое {}, второе {}) без ручного ввода первого, второго и т. д. Я имею в виду, есть ли другой способ? - person Korovjov; 18.02.2020

Вы не устанавливаете свои данные this.setState для компонентов класса. Замените this.setState на setApiData().

useState возвращает начальное состояние и функцию для обновления этого значения.

const [ hasError, setHasErrors] = useState(false);

.then(res => res.json())
.then(res => {
  setApiData(res)
})
.catch(() => setHasErrors(true))
);

Как указал Джордж, начальное состояние установлено пустым, выполнение props.content.first.image приведет к ошибке. Либо установите начальное значение для объекта, например

const [ fetchApiData, setApiData ] = useState({
   first: {},
   second: {}
});

или проверьте значения в вашем компоненте.

const Index = props => {

  return (
   <View>
    <BigNews
    image={props && props.content && props.content.first && props.content.first.image}
    pretitle={props && props.content && props.content.pretitle && props.content.first.pretitle}
    title={props && props.content && props.content.title && props.content.first.title}
    introduction={props && props.content && props.content.introduction && props.content.first.introduction}
    style={{color: props && props.content && props.content.first && props.content.first.mark}}/>

    ...
  </View>
  );
}
export default Index;
person Junius L.    schedule 17.02.2020
comment
@Korovjov Обратите внимание, что, хотя это не является причиной ошибки, которую вы получаете, она по-прежнему верна. - person George; 18.02.2020
comment
TypeError: undefined не является объектом (оценка 'props.content.first') - person Korovjov; 18.02.2020
comment
Ответ Джорджа о состоянии, как вы указали, верен. Нет проблем. Но теперь React выдает ошибку TypeError destroy is not a function. И я вообще не могу найти эту ошибку в гугле. - person Korovjov; 18.02.2020