Не получаю данные из 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;
|
riaron86, у тебя АПИ и реакт крутятся на разных "серверах".
Таким образом ты не туда обращаешься Цитата:
Скорее всего сервер будет доступен на http://localhost:3001/api |
React.useEffect(() => {
fetch('http://localhost:3001/api') .then((res) => res.json()) .then((data) => setData(data.message)); }, []); пишет failed to fetch |
Ты не можешь просто взять и запросить данные с другим origin с клиента, это небезопасно. Тебе либо надо добавить со стороны сервера заголовки access-control-allow-origin это разрешающие, либо настроить devserver proxy(есть их коробки в большинстве случаев), который будет проксировать прозрачно запросы с /api на сервер в процессе разработке.
Предпочтителен второй вариант, т.к. затрагивает только dev конфигурацию, не требуя изменения кода в последствии для прода. |
С этим я потом разберусь. Почему код не работает
|
Цитата:
Цитата:
На каком порту он у тебя запущен? |
При вводе 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) |
Цитата:
http://localhost:3001/ - это другой origin по сравнию с http://localhost:3000/ на котором у тебя крутится клиент. Незя слать запросы на другой origin без разрешения. Также я написал как решить проблему. Первый вариант явно разрешит такое поведение. Второй сделает так что запрос /api(http://localhost:3000/api) будет прозрачно проксирован на http://localhost:3001/api devserver'ом. |
добавил строчку
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 |
Цитата:
|
вот весь пароект
https://dropmefiles.com/smOr9 |
выдает ошибку
(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;
|
->
fetch('http://localhost:3001/api')
|
теперь пишет что не может спарсить, что делать
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 |
riaron86, а прочитать что тебе написало и приглядеться?
|
Между localhost и /api есть кавычка но в коде её нет
|
riaron86, космические лучи, вестимо.
В коде её не может не быть, смотри внимательно, сделай полнотекстовый поиск... |
теперь нет ошибок но значение 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}`);
});
|
fetch - асинхронная функция. Она возвращает промис
res.json - тоже асинхронная. Я не знаток реакта, но fetch надо вызывать как то так
fetch('http://localhost:3001/api',{mode: 'no-cors'})
.then( res => res.json())
.then (data => setData(data) )
|
И {mode: 'no-cors'} убрать. Это не магия которая позволит тебе делать кросдоменные запросы без разрешения. Этот заголовок позволяет отравить кросдоменный запрос, но запрещает получение ответа.
И 'Access-Control-Allow-Origin' должен быть не 'https://localhost:3001'(сервер), а 'https://localhost:3000'(клиент) - url тут означает кому ты разрешаешь, а не кто разрешает(что и так ясно). Ну и проще '*' поставить для разработки и не париться. Всё равно в проде удалять. voraa, у него в предыдущем посте всё нормально было с вызовом, техно-шаманит видать, буковки переставляя в надежде на чудо. |
удалил 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}`);
});
|
Установите Access-Control-Allow-Origin: '*'
И не парьтесь У вас пока все на localhost. У вас есть сертификат для него, что бы указывать https? |
Спасибо, помогло! Но как будет правильнее написать для безопасности?
|
С какого адреса приходит страница (какой url пишется в браузере)?
Тот же host должен быть указан в Access-Control-Allow-Origin. Т.е сервер разрешает получать корс ответы страницам, вызванным с этого хоста. |
riaron86, на продакшене у тебя скорее всего и клиент и сервер будут развёрнуты с одного адреса. Тогда просто надо будет убрать Access-Control-Allow-Origin и всё.
|
| Часовой пояс GMT +3, время: 16:44. |