Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   Не получаю данные из node в react (https://javascript.ru/forum/node-js-io-js/85223-ne-poluchayu-dannye-iz-node-v-react.html)

riaron86 18.05.2023 20:20

Не получаю данные из node в react
 
index.js
const express = require("express");

const PORT = process.env.PORT || 3001;

const app = express();
app.get("/api", (req, res) => {
    res.json({ message: "Hello from server!" });
});


app.listen(PORT, () => {
    console.log(`Server listening on ${PORT}`);
});

App.js
import React from "react";
import Shop from "./pages/Shop";

// client/src/App.js
function App({arrayse}) {
    const [data, setData] = React.useState(null);

    React.useEffect(() => {
        fetch("/api")
            .then((res) => res.json())
            .then((data) => setData(data.message));
    }, []);
    return (
        <div className="App">
            <header className="App-header">
                <p>{!data ? "Loading..." : data}</p>
            </header>

        <Shop arrayse={arrayse}/>
        </div>
    )
}

export default App;

ksa 18.05.2023 22:48

riaron86, у тебя АПИ и реакт крутятся на разных "серверах".

Таким образом ты не туда обращаешься
Цитата:

Сообщение от riaron86
fetch("/api")


Скорее всего сервер будет доступен на http://localhost:3001/api

riaron86 19.05.2023 09:41

React.useEffect(() => {
fetch('http://localhost:3001/api')
.then((res) => res.json())
.then((data) => setData(data.message));
}, []);
пишет failed to fetch

Aetae 19.05.2023 10:59

Ты не можешь просто взять и запросить данные с другим origin с клиента, это небезопасно. Тебе либо надо добавить со стороны сервера заголовки access-control-allow-origin это разрешающие, либо настроить devserver proxy(есть их коробки в большинстве случаев), который будет проксировать прозрачно запросы с /api на сервер в процессе разработке.

Предпочтителен второй вариант, т.к. затрагивает только dev конфигурацию, не требуя изменения кода в последствии для прода.

riaron86 19.05.2023 11:43

С этим я потом разберусь. Почему код не работает

ksa 19.05.2023 11:56

Цитата:

Сообщение от riaron86
пишет failed to fetch

Ты полностью покажи текст ошибки...

Цитата:

Сообщение от riaron86
Почему код не работает

Ты в браузере, набирая УРЛ запроса, получаешь ответ от сервера?

На каком порту он у тебя запущен?

riaron86 19.05.2023 13:16

При вводе localhost:3001 ответ получаю
вот ошибка

Uncaught runtime errors:
×
ERROR
Failed to fetch
TypeError: Failed to fetch
at http://localhost:3000/static/js/bundle.js:36:5
at commitHookEffectListMount (http://localhost:3000/static/js/bundle.js:27138:30)
at commitPassiveMountOnFiber (http://localhost:3000/static/js/bundle.js:28631:17)
at commitPassiveMountEffects_complete (http://localhost:3000/static/js/bundle.js:28603:13)
at commitPassiveMountEffects_begin (http://localhost:3000/static/js/bundle.js:28593:11)
at commitPassiveMountEffects (http://localhost:3000/static/js/bundle.js:28583:7)
at flushPassiveEffectsImpl (http://localhost:3000/static/js/bundle.js:30468:7)
at flushPassiveEffects (http://localhost:3000/static/js/bundle.js:30420:18)
at http://localhost:3000/static/js/bundle.js:30235:13
at workLoop (http://localhost:3000/static/js/bundle.js:37373:38)

Aetae 19.05.2023 14:55

Цитата:

Сообщение от riaron86 (Сообщение 551937)
С этим я потом разберусь. Почему код не работает

Я написал "почему не работает", лол.
http://localhost:3001/ - это другой origin по сравнию с http://localhost:3000/ на котором у тебя крутится клиент. Незя слать запросы на другой origin без разрешения.

Также я написал как решить проблему. Первый вариант явно разрешит такое поведение. Второй сделает так что запрос /api(http://localhost:3000/api) будет прозрачно проксирован на http://localhost:3001/api devserver'ом.

riaron86 19.05.2023 16:53

добавил строчку
res.set('Access-Control-Allow-Origin', 'http://localhost:3000');
const app = express();
app.get("/api", (req, res) => {
    res.set('Access-Control-Allow-Origin', 'http://localhost:3000');
    res.json({ message: "Hello from server!" });
});

вот какие ошибки выдает
3000/api. URL scheme "localhost" is not supported.
(анонимный) @ App.js:9
commitHookEffectListMount @ react-dom.development.js:23150
commitPassiveMountOnFiber @ react-dom.development.js:24926
commitPassiveMountEffects_complete @ react-dom.development.js:24891
commitPassiveMountEffects_begin @ react-dom.development.js:24878
commitPassiveMountEffects @ react-dom.development.js:24866
flushPassiveEffectsImpl @ react-dom.development.js:27039
flushPassiveEffects @ react-dom.development.js:26984
(анонимный) @ react-dom.development.js:26769
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533
App.js:9

Uncaught (in promise) TypeError: Failed to fetch
at App.js:9:1
at commitHookEffectListMount (react-dom.development.js:23150:1)
at commitPassiveMountOnFiber (react-dom.development.js:24926:1)
at commitPassiveMountEffects_complete (react-dom.development.js:24891:1)
at commitPassiveMountEffects_begin (react-dom.development.js:24878:1)
at commitPassiveMountEffects (react-dom.development.js:24866:1)
at flushPassiveEffectsImpl (react-dom.development.js:27039:1)
at flushPassiveEffects (react-dom.development.js:26984:1)
at react-dom.development.js:26769:1
at workLoop (scheduler.development.js:266:1)
(анонимный) @ App.js:9
commitHookEffectListMount @ react-dom.development.js:23150
commitPassiveMountOnFiber @ react-dom.development.js:24926
commitPassiveMountEffects_complete @ react-dom.development.js:24891
commitPassiveMountEffects_begin @ react-dom.development.js:24878
commitPassiveMountEffects @ react-dom.development.js:24866
flushPassiveEffectsImpl @ react-dom.development.js:27039
flushPassiveEffects @ react-dom.development.js:26984
(анонимный) @ react-dom.development.js:26769
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533
Promise.then (асинхронно)
(анонимный) @ App.js:9
commitHookEffectListMount @ react-dom.development.js:23150
commitPassiveMountOnFiber @ react-dom.development.js:24926
commitPassiveMountEffects_complete @ react-dom.development.js:24891
commitPassiveMountEffects_begin @ react-dom.development.js:24878
commitPassiveMountEffects @ react-dom.development.js:24866
flushPassiveEffectsImpl @ react-dom.development.js:27039
flushPassiveEffects @ react-dom.development.js:26984
(анонимный) @ react-dom.development.js:26769
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533

ksa 19.05.2023 17:09

Цитата:

Сообщение от riaron86
"localhost" is not supported

Замени на ИП адрес 127.0.0.1

riaron86 19.05.2023 21:19

вот весь пароект
https://dropmefiles.com/smOr9

riaron86 22.05.2023 10:07

выдает ошибку
(in promise) SyntaxError: Unexpected token '<', "<html>
<"... is not valid JSON
Promise.then (асинхронно)
(анонимный) @ App.js:9
commitHookEffectListMount @ react-dom.development.js:23150
commitPassiveMountOnFiber @ react-dom.development.js:24926
commitPassiveMountEffects_complete @ react-dom.development.js:24891
commitPassiveMountEffects_begin @ react-dom.development.js:24878
commitPassiveMountEffects @ react-dom.development.js:24866
flushPassiveEffectsImpl @ react-dom.development.js:27039
flushPassiveEffects @ react-dom.development.js:26984
(анонимный) @ react-dom.development.js:26769
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533
index.js//сервер
const express = require("express");

const PORT = process.env.PORT || 3001;

const app = express();
app.get("/api", (req, res) => {
    res.set('Access-Control-Allow-Origin', 'http://localhost:3000/');

    res.json({ message: "Hello from server!" });
});


app.listen(PORT, () => {
    console.log(`Server listening on ${PORT}`);
});

index.js//клиент
import React,{createContext, useContext} from 'react';
import ReactDOM from 'react-dom/client';
import App from './App.js';
const Context = createContext(null)
const arrayse=[
    {'id':1,'description':'description1'},
    {'id':2,'description':'description2'},
    {'id':3,'description':'description3'},
    {'id':4,'description':'description4'},
    {'id':5,'description':'description5'},
]

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Context.Provider value={{arrayse:arrayse}}>
        <App arrayse={arrayse}/>
    </Context.Provider>
);

app.js

import React from "react";
import Shop from "./pages/Shop";

// client/src/App.js
function App({arrayse}) {
    const [data, setData] = React.useState(null);

    React.useEffect(() => {
        fetch('http://localhost:3000/api')
            .then((res) => res.json())
            .then((data) => setData(data.message));
    }, []);
    return (
        <div className="App">
            <header className="App-header">
                <p>{!data ? "Loading..." : data}</p>
            </header>

        <Shop arrayse={arrayse}/>
        </div>
    )
}

export default App;

Aetae 23.05.2023 15:05

->
fetch('http://localhost:3001/api')

riaron86 23.05.2023 22:13

теперь пишет что не может спарсить, что делать
Failed to execute 'fetch' on 'Window': Failed to parse URL from http://localhost:3001`/api
at App.js:9:1
at commitHookEffectListMount (react-dom.development.js:23150:1)
at commitPassiveMountOnFiber (react-dom.development.js:24926:1)
at commitPassiveMountEffects_complete (react-dom.development.js:24891:1)
at commitPassiveMountEffects_begin (react-dom.development.js:24878:1)
at commitPassiveMountEffects (react-dom.development.js:24866:1)
at flushPassiveEffectsImpl (react-dom.development.js:27039:1)
at flushPassiveEffects (react-dom.development.js:26984:1)
at react-dom.development.js:26769:1
at workLoop (scheduler.development.js:266:1)
(анонимный) @ App.js:9
commitHookEffectListMount @ react-dom.development.js:23150
commitPassiveMountOnFiber @ react-dom.development.js:24926
commitPassiveMountEffects_complete @ react-dom.development.js:24891
commitPassiveMountEffects_begin @ react-dom.development.js:24878
commitPassiveMountEffects @ react-dom.development.js:24866
flushPassiveEffectsImpl @ react-dom.development.js:27039
flushPassiveEffects @ react-dom.development.js:26984
(анонимный) @ react-dom.development.js:26769
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533

Aetae 23.05.2023 23:14

riaron86, а прочитать что тебе написало и приглядеться?

riaron86 24.05.2023 12:08

Между localhost и /api есть кавычка но в коде её нет

Aetae 24.05.2023 18:25

riaron86, космические лучи, вестимо.

В коде её не может не быть, смотри внимательно, сделай полнотекстовый поиск...

riaron86 28.05.2023 13:01

теперь нет ошибок но значение data undfined

App.js
import React from "react";
import Shop from "./pages/Shop";

// client/src/App.js
function App({arrayse}) {
    const [data, setData] = React.useState(null);

    React.useEffect(() => {
      const res=  fetch('http://localhost:3001/api',{mode: 'no-cors'});

        setData(res.json);
    }, []);
    console.log(data);

    return (
        <div className="App">
            <header className="App-header">
                <p>{!data ? "Loading..." : data}</p>
            </header>
        <Shop arrayse={arrayse}/>
        </div>
    )
}

export default App;

index.php
const express = require("express");
const PORT =  3001;

const app = express();

app.get("/api", (req, res) => {
    res.set('Access-Control-Allow-Origin', 'https://localhost:3001',{mode: 'no-cors'});

    res.json({ message: "Hello from server!" });
});


app.listen(PORT, () => {
    console.log(`Server listening on ${PORT}`);
});

voraa 28.05.2023 14:06

fetch - асинхронная функция. Она возвращает промис
res.json - тоже асинхронная.
Я не знаток реакта, но fetch надо вызывать как то так

fetch('http://localhost:3001/api',{mode: 'no-cors'})
   .then( res => res.json())
   .then (data => setData(data) )

Aetae 28.05.2023 15:56

И {mode: 'no-cors'} убрать. Это не магия которая позволит тебе делать кросдоменные запросы без разрешения. Этот заголовок позволяет отравить кросдоменный запрос, но запрещает получение ответа.

И 'Access-Control-Allow-Origin' должен быть не 'https://localhost:3001'(сервер), а 'https://localhost:3000'(клиент) - url тут означает кому ты разрешаешь, а не кто разрешает(что и так ясно). Ну и проще '*' поставить для разработки и не париться. Всё равно в проде удалять.

voraa, у него в предыдущем посте всё нормально было с вызовом, техно-шаманит видать, буковки переставляя в надежде на чудо.

riaron86 28.05.2023 18:06

удалил cors из сервера и клиента но все равно но все рано сервер блочит запрос.
host:3001/api' from origin 'http://localhost:3000' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://localhost:3001' that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
App.js:9
что переводится как
'https://localhost:3001 - это не соответствует указанному источнику происхождения. Попросите сервер отправить заголовок с допустимым значением или, если вам нужен непрозрачный ответ, установите режим запроса на "no-cors", чтобы получить ресурс с отключенным CORS.
App.js:9

GET http://localhost:3001/api net::ERR_FAILED 200 (OK)
(анонимный) @ App.js:9
commitHookEffectListMount @ react-dom.development.js:23150
commitPassiveMountOnFiber @ react-dom.development.js:24926
commitPassiveMountEffects_complete @ react-dom.development.js:24891
commitPassiveMountEffects_begin @ react-dom.development.js:24878
commitPassiveMountEffects @ react-dom.development.js:24866
flushPassiveEffectsImpl @ react-dom.development.js:27039
flushPassiveEffects @ react-dom.development.js:26984
(анонимный) @ react-dom.development.js:26769
workLoop @ scheduler.development.js:266
flushWork @ scheduler.development.js:239
performWorkUntilDeadline @ scheduler.development.js:533
App.js:9
вот мой код
client App.js:
import React from "react";
import Shop from "./pages/Shop";

// client/src/App.js
function App({arrayse}) {
    const [data, setData] = React.useState(null);
    React.useEffect(() => {

         fetch('http://localhost:3001/api',)
            .then( res => res.json())
            .then (data => setData(data))
    }, []);
    console.log(data);

    return (
        <div className="App">
            <header className="App-header">
                <p>{!data ? "Loading..." : data}</p>
            </header>
        <Shop arrayse={arrayse}/>
        </div>
    )
}

export default App;

server index.js:
const express = require("express");
const PORT =  3001;

const app = express();

app.get("/api", (req, res) => {
    res.set('Access-Control-Allow-Origin', 'https://localhost:3001');

    res.json({ message: "Hello from server!" });
});


app.listen(PORT, () => {
    console.log(`Server listening on ${PORT}`);
});

voraa 28.05.2023 18:21

Установите Access-Control-Allow-Origin: '*'
И не парьтесь

У вас пока все на localhost. У вас есть сертификат для него, что бы указывать https?

riaron86 28.05.2023 21:50

Спасибо, помогло! Но как будет правильнее написать для безопасности?

voraa 28.05.2023 22:39

С какого адреса приходит страница (какой url пишется в браузере)?
Тот же host должен быть указан в Access-Control-Allow-Origin.
Т.е сервер разрешает получать корс ответы страницам, вызванным с этого хоста.

Aetae 29.05.2023 10:31

riaron86, на продакшене у тебя скорее всего и клиент и сервер будут развёрнуты с одного адреса. Тогда просто надо будет убрать Access-Control-Allow-Origin и всё.


Часовой пояс GMT +3, время: 08:25.