ожидаемое назначение или вызов функции: функциональный компонент ReactJS без неиспользуемых выражений

#javascript #reactjs #use-effect

#javascript #reactjs #использование-эффект

Вопрос:

это мое первое приложение react, и я не понимаю, что не так.Я пытаюсь отобразить страницу, но дважды получаю ошибку в заголовке (в строках 26: 5, где fetch(url, { находится, и 39: 9, где у меня есть строка setisLoaded(true), setArticles(result.articles);) .Я менял код взад и вперед с компонента класса приложения на функциональный компонент, но безуспешно (хотя выборка данных работает / сработала).Я попытался включить весь код внутри метода useEffect() в оператор return только для того, чтобы получить всевозможные ошибки синтаксического анализа, которые я не могу исправить.Итак, вот код:

 import React, { Fragment, useState, useEffect } from 'react';
    import Title from './components/Title/Title';
    import Content from './components/Content/Content';
    import 'bootstrap/dist/css/bootstrap.min.css';
    import { Card, Navbar, Form, FormControl, Button } from 'react-bootstrap';
    
    const App = (props) => {
      const [error, setError] = useState(null);
      const [isLoaded, setisLoaded] = useState(false);
      const [articles, setArticles] = useState([]);
      const [country, setCountry] = useState('gb');
    
      const handleSubmit = (event) => {
        event.preventDefault();
        changeCountryHandler();
      };
    
      const changeCountryHandler = (event) => {
        setCountry(event.target.value);
      };
    
      useEffect(() => {
        let url =
          'https://cors-anywhere.herokuapp.com/http://newsapi.org/v2/top-headlines?country='
 
          country;
        fetch(url, {
          method: 'GET',
          headers: {
            Accept: 'application/json, text/plain, */*',
            'Content-type': 'application/json',
            'x-api-key': 'myApiKey',
            SameSite: 'None',
          
          },
        })
          .then((res) => res.json())
    
          .then((result) => {
            setisLoaded(true), setArticles(result.articles);
          }),
          (error) => {
            setisLoaded(true);
            setError(error);
          };
      });
    
      if (error) {
        return <div>Error: {error.message}</div>;
      } else if (!isLoaded) {
        return <div>Loading...</div>;
      } else {
        return (
          <>
            <Navbar className="bg-secondary justify-content-between" variant="dark">
              <p>The selected country is:{country}</p>
              <Form inline onSubmit={handleSubmit}>
                <FormControl
                  type="text"
                  placeholder="Search by country"
                  className=" mr-sm-2"
                  onChange={changeCountryHandler}
                  value={country}
                />
                <Button type="submit">Submit</Button>
              </Form>
            </Navbar>
            {articles.map((article) => (
              <Card
                style={{ width: '100%', height: 'auto' }}
                key={article.title}
                className="mb-5 mt-4 bg-light"
              >
                <Card.Img
                  variant="top"
                  src={article.urlToImage}
                  className="pr-3 pl-3"
                  alt=""
                />
    
                <Card.Body>
                  <Card.Title>
                    {article.author} | {article.publishedAt}
                    <Title title={article.title}>{article.title}</Title>
                  </Card.Title>
                  Description: {article.description}
                  <Content content={article.content}>{article.content}</Content>
                  Read the full article on{' '}
                  <Card.Link
                    href={article.url}
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    {article.url}
                  </Card.Link>
                </Card.Body>
              </Card>
            ))}
          </>
        );
      }
    };
    
    export default App;
  

Изначально я хотел иметь возможность изменять параметр country из URL, чтобы извлекать желаемый контент из API на основе того, что отправлено из формы (я знаю, что у меня должен быть выбор с параметрами вместо текста типа ввода, но я просто тестирую это сейчас).Но на данный момент я просто рад, если смогу отобразить любую страницу, поскольку другие ответы на эту проблему (добавление возврата к функции стрелки useEffect (), заключение операторов в круглые скобки вместо фигурных скобок) не сработали для меня, и я не понимаю эту ошибку.Любая идея будет оценена.

Ответ №1:

Одна ошибка для этих:

 setisLoaded(true), setArticles(result.articles);
  

Инструкции разделяются точкой с запятой, а не запятыми, поэтому исправление:

 setisLoaded(true);
setArticles(result.articles);
  

Одна ошибка — это неуместные круглые скобки, из-за чего обратный вызов ошибки является отдельным выражением:

 }), // <-----
(error) => {
  setisLoaded(true);
  setError(error);
};
  

Вместо этого должно быть:

 }, (error) => {
  setisLoaded(true);
  setError(error);
}); // <----- moved to here
  

Комментарии:

1. Спасибо за ответ. Это решило проблему, но теперь у меня есть другая. Теперь у меня ошибка: неожиданный токен T в JSON в позиции 0 ошибка. Многие запросы продолжают отправляться на этот сервер, у меня было несколько сотен отправленных запросов за 30 секунд, я заполняю сервер. Что может быть причиной этого?

2. Ваш компонент настроен на отправку запроса при каждом рендеринге. Если вы хотите отправить его только после монтирования компонента, вам нужно будет добавить пустой массив зависимостей в конце вашего useEffect. useEffect(() => { /*your existing effect code here */ }, [])

Ответ №2:

Вам не хватает массива зависимостей в useEffect.

 useEffect(() => {
   //your code
}, []);
  

Если вы добавите пустой массив, он будет извлекать данные только один раз, когда ваш компонент монтируется. Если вы добавите какой-либо реквизит или состояние внутри массива, он будет извлекаться при монтировании компонента, а также при изменении реквизита или добавленного состояния.

Всегда не забывайте добавлять массив в качестве второго параметра useEffect, чтобы избежать этого бесконечного цикла.

Комментарии:

1. Спасибо Николасу и Андони. Это решило мою проблему.