#javascript #reactjs #rest #axios #react-hooks
#javascript #reactjs #отдых #axios #реагирующие перехваты
Вопрос:
Я получаю сообщение об ошибке, когда мой компонент диаграммы отображается из-за его начального состояния, которое является пустым массивом перед ответом API. Было бы сказано что-то вроде Cannot read property '0' of undefined
, что связано с тем, что при загрузке компонента его начальное состояние, ну … пустой массив. Итак, я хотел бы знать, есть ли способ заставить компонент отображаться только после получения ответа API.
Вот родительский компонент:
function InformationPage({
match: {
params: { symbol },
},
}) {
const [chartData, setChartData] = useState([]); {/*Declaring state*/}
useEffect(() => { {/*Fetching API response here to set state*/}
axios
.get(
`https://finnhub.io/api/v1/stock/candle?symbol=${symbol}amp;resolution=15amp;from=1572651390amp;to=1602623478amp;token=xxxxxxxxx`
)
.then((res) => {
console.log(res.data);
setChartData(res.data);
})
.catch((err) => {
console.log(err);
});
}, [symbol]);
return (
<Grid item container xs={12} sm={12} md={6} lg={8}>
{chartData amp;amp; <QuoteChart chartData={chartData} iex={iex} />}
</Grid>
);
}
export Default InformationPage;
Вот дочерний компонент диаграммы, в основном, когда я выполняю запрос на выборку из axios, он возвращает массив, который будет отображен в chartRender
объекте. Мне просто нужно найти способ рендеринга компонента только ПОСЛЕ завершения запроса api от axios, чтобы не было ошибки. Любая помощь будет высоко оценена.
function QuoteChart(props) {
const classes = useStyles();
const { chartData } = props;
const chartRender = chartData.map((chartConfig) => ({
x: new Date(chartConfig?.t),
y: [chartConfig?.o, chartConfig?.h, chartConfig?.l, chartConfig?.c],
}));
// const chartDataLog = console.log(chartData);
const config = {
series: [
{
data: [{ chartRender }],
},
],
Ответ №1:
Обновление: согласно API Finnhub, это объект, который вы получаете от API, а не массив. Это означает, что charData.length
в моем предыдущем ответе никогда не будет оцениваться true
, и дочерний компонент QuoteChart
никогда не будет отображаться.
Я бы предложил следующие изменения. В вашем родительском компоненте сделайте charData = null
изначально:
const [chartData, setChartData] = useState(null);
Когда API вернул ответ и chartData
ему было присвоено значение, ваш дочерний компонент может быть отображен:
{chartData amp;amp; <QuoteChart chartData={chartData} iex={iex} />}
Диаграмма, которую вы хотите отобразить в дочернем компоненте, ожидает следующих входных данных: [{ x: date, y: [O,H,L,C] }]
. Поскольку map()
может вызываться только для массивов и chartData
не является таковым, вам следует перейти к одному из массивов внутри указанного объекта, например chartData.t
:
const chartRender = chartData.t.map((timestamp, index) => ({
x: new Date(timestamp),
y: [chartData.o[index], chartData.h[index], chartData.l[index], chartData.c[index]],
}));
Наконец, series.data
ожидает массив, вам не нужно дополнительно оборачивать его в объект. Так что это должно сработать:
const config = {
series: [{
data: chartRender
}]
};
Вы инициализируете chartData
с помощью пустого массива, поэтому ваше условие должно выглядеть следующим образом:
{chartData.length amp;amp; <QuoteChart chartData={chartData} iex={iex} />}
Если вы ожидаете, что API вернет пустой список, я бы рекомендовал установить undefined
или null
в качестве начального значения chartData
:
const [chartData, setChartData] = useState(null);
В этом случае вы можете сохранить свое состояние как есть.
Комментарии:
1. Я использовал
chartData.length
, но когда я консоль. войдитеchartData
из дочернего компонента, ничего не отображается. Я перестал получать ошибки, но компонент тоже не отображался.2. @Pacholoamit Каков результат
console.log(res.data);
, когда вы получаете ответ от API?3. Я настрою codepen, чтобы вы могли помочь мне взглянуть. Это действительно сбивает меня с толку. Я прокомментирую это здесь через несколько минут. Могу ли я как-нибудь пообщаться с вами, если это нормально? Я женщина-программист, и я была бы признательна, если бы мне было к кому обратиться, если у меня возникнут проблемы. Но если вам это не нравится, тогда ответ на этот вопрос подойдет. Теперь я настрою codepen из своего репозитория.
4. Пожалуйста, посмотрите мой обновленный ответ, надеюсь, это поможет. Всегда полезно иметь ссылку на Codepen.
5. Здравствуйте, извините за поздний ответ. Вот codesandbox в codesandbox, в котором говорится
Cannot read property 'map' of undefined
, однако на моем локальном хостинге говоритсяUnhandled Rejection (Error): Please provide [Open, High, Low and Close] values in valid format. Read more https://apexcharts.com/docs/series/#candlestick
, что я создал консоль. журнал и все нормально отображается с точки зрения вывода функции map, но я получаю ошибку apexchart, в которой говорится, что формат неверен. Дайте мне знать, что вы думаете.
Ответ №2:
Если я не ошибаюсь, вы можете просто использовать async / await для своей проблемы. Поэтому измените строку useEffect на
useEffect(async () => { {/*Fetching API response here to set state*/}
и затем
await axios
.get(
`https://finnhub.io/api/v1/stock/candle?symbol=${symbol}amp;resolution=15amp;from=1572651390amp;to=1602623478amp;token=xxxxxxxxx`
)
Затем ваше приложение должно дождаться завершения выборки axios
Комментарии:
1. Вы не можете передать асинхронную функцию
useEffect
.
Ответ №3:
Вам нужно обернуть вызов axios в асинхронную функцию и wait
там
useEffect(() => { {/*Fetching API response here to set state*/}
const getInfo = async () => {
await res = axios
.get(
`https://finnhub.io/api/v1/stock/candle?symbol=${symbol}amp;resolution=15amp;from=1572651390amp;to=1602623478amp;token=xxxxxxxxx`
)
console.log(res.data);
setChartData(res.data);
}
getInfo()
}, [symbol]);
Комментарии:
1. useEffect запустится после монтирования, как это поможет
2. или, может быть, вы намеренно пропустили часть проверки перед рендерингом компонента
Ответ №4:
Самый простой способ потребует простого небольшого изменения вашего кода:
{chartData.length amp;amp; <QuoteChart chartData={chartData} iex={iex} />}
После исследования finnhub — я вижу, что ответ не является массивом.
Я протестировал этот URL:
https://finnhub.io/api/v1/stock/candle?symbol=AAPLamp;resolution=15amp;from=1572651390amp;to=1602623478amp;token=
Ответ представляет собой объект со свойством «c».
Ваш код должен быть соответствующим образом изменен.
Для приведенного выше примера ссылки:
setChartData(res.data.c);
Комментарии:
1. Я использовал chartData.length, но когда я консоль. регистрируйте данные диаграммы из дочернего компонента, ничего не отображается. Я перестал получать ошибки, но компонент тоже не отображался.
2. если дочерний компонент ничего не отображает, это означает, что chartData.length имеет значение false, что означает, что это либо пустой массив, либо объект, либо число… Вы уверены, что chartData — это массив?
3. Вот что я получаю при консоли. запишите ответ api как есть.
4. В принципе, вы должны проверить res.data.s на статус — это либо «ok», либо «no_data». Затем вы должны использовать интересующие вас данные. Вам следует подробнее ознакомиться с API finnhub: finnhub.io/docs/api#stock-candles .
5. это apex chart, библиотека, которую я использую. Finnhub работает на 100% все время, и я уверен, что вы проверяли. API возвращает массивы o, h, l и c. Вот почему я только что сделал res.data, потому что я бы обращался к массивам o, h, l и, c в компоненте диаграммы, но при первоначальном рендеринге он продолжает выдавать сообщение об ошибке «Невозможно прочитать свойство [0] неопределенного». Мне просто нужно, чтобы диаграмма отображалась один раз в apiзапрос завершен, поэтому я могу передать массивы o, h, l и c функции отображения в дочернем компоненте, который отвечает за данные на диаграмме. Спасибо за помощь младшему разработчику.