页面重新加载后的不同行为(应用程序处于生产模式,由 React 和 Express 制作)
Different behavior after page is reloaded (app is in production mode, made by react and express)
在开发模式下一切正常。乍一看,应用程序在构建模式下是相同的(我在服务器端使用 express)。但是当我尝试刷新我的页面时(url 包含参数)我收到
只有
{
surveyString: "[{"type":"radiogroup","name":"Favorite Character?","title":"Favorite Character?","isRequired":true,"colCount":1,"choices":["Walt","Hank","Jesse","Mike"]},{"type":"radiogroup","name":"Favorite Actor?","title":"Favorite Actor?","isRequired":true,"colCount":1,"choices":["Aaron Paul","Bryan Cranston","Jonathan Banks"]}]",
surveyTitle: "Breaking Bad Survey"
}
这是从服务器发送的响应,这当然是我想要的,但不知何故应用程序没有合并它。
我在 Chrome 中收到的错误是
Not allowed to load local resource: view-source
在 Firefox 中,错误看起来有些不同
Content Security Policy: The page’s settings blocked the loading of a resource a ...resource link...
通过这些错误,我承认了有关内容安全策略、快递包如何克服它的一些基本方法等等……但那是另一回事,我希望我能在反应方面解决问题。
我很乐观,因为我在其他页面上的 href links 有相同的行为。当我用 LinkTo 应用程序替换 aHref 时,工作正常。
我点击link,在新页面上一切正常,直到我刷新。
link 是到 github 页:
component which not survives refresh
function SingleSurvey(props) {
const [complete, setComplete] = useState(false);
const [voted, setVoted] = useState(false);
const [json, setJson] = useState({});
const [title, setTitle] = useState("");
const [resultsDisplay, setResultsDisplay] = useState(false);
const { id } = useParams();
useEffect(() => {
surveyServices.getSingle(id).then((res) => {
const stringQuestions = JSON.parse(res.surveyString);
setJson({ questions: stringQuestions });
setTitle(res.surveyTitle);
});
}, [id]);
useEffect(() => {
const checkItem = window.localStorage.getItem(`chartVoted-${id}`);
if (checkItem) {
setVoted(true);
}
// eslint-disable-next-line
}, []);
function onComplete(result) {
surveyServices.updateVotes({
data: result.data,
id,
});
window.localStorage.setItem(`chartVoted-${id}`, true);
setComplete(true);
setTimeout(() => {
window.location.reload();
}, 1100);
}
return (
<main className="survey-page">
{complete && <p className="survey-finished"></p>}
{!voted ? (
<>
<Survey.Survey
json={json}
showCompletePage={false}
onComplete={(result) => onComplete(result)}
/>
<div className="show-results">
<button
className="btn-results"
onClick={() => setResultsDisplay(!resultsDisplay)}
>
{resultsDisplay ? "Hide Charts" : "Show Charts"}
</button>
<div
className="visible-results"
style={{ display: resultsDisplay ? "" : "none" }}
>
<Result id={id} title={title} />
</div>
</div>
</>
) : (
<div className="just-results">
<Result id={id} title={title} />
</div>
)}
</main>
);
}
export default SingleSurvey;
<Router>
<Notification />
<Switch>
<Route exact path="/api/survey/single/:id" component={SingleSurvey} />
</Switch>
</Router>
ReactDOM 渲染,我使用的是基本的 redux
<Provider store={store}>
<App />
</Provider>,
app.use(express.static(path.join(__dirname, "build")));
app.use("/api/survey", surveyController);
app.use("/api/users", usersController);
app.use("/api/login", loginController);
app.get("/", function (req, res) {
app.get("/*", function (req, res) {
res.sendFile(path.join(__dirname, "build", "index.html"));
});
});
如果想直接看问题app is uploaded on heroku.
希望不要错过任何有价值的信息。有人知道如何解决令人难以置信的恼人问题吗?
您混淆了您的 API 路由和您的客户端路由,因此导致超载。
当 Web 浏览器访问网站时,它们会发出 GET 请求,这与您与 Express 服务器交互的方式完全相同。
您的问题是您通过将用户重定向到向您的服务器发出 GET 请求的服务器端点,不小心向您的服务器发出了 get 请求。
发生了什么事
Url 更改由 Link
组件触发(不在您提供的代码中
React Router 匹配 URL 而不会触发 API 请求(这是单页网络应用程序的工作方式)
<Route exact path="/api/survey/single/:id" component={SingleSurvey} />
页面刷新 Express 匹配 URL 和 returns API 响应而不是 index.html
app.use("/api/survey", surveyController);
解决方案
- 将您的 client-side 路径更改为:
/client/survey
根据 Alex Mckay 的回答,我更改了路线位置
<Route
exact
path="/client/survey/single/:id"
component={SingleSurvey}
/>
然后修复我服务器端的内容安全策略错误。
这对我来说是一个全新的领域,所以我在控制台中跟踪错误并一一修复。
使用 [helmet-csp] 包是非常直观的过程。
app.use(
csp({
directives: {
defaultSrc: ["'self'"],
fontSrc: ["https://fonts.googleapis.com/", "https://fonts.gstatic.com"],
connectSrc: ["'self'", "http://localhost:3005"],
styleSrc: [
"'self'",
"'unsafe-inline'",
"https://surveyjs.azureedge.net/1.8.0/modern.css",
"https://fonts.googleapis.com",
"'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='",
"'sha256-OTeu7NEHDo6qutIWo0F2TmYrDhsKWCzrUgGoxxHGJ8o='",
],
imgSrc: ["'self'", "http://localhost:3005"],
scriptSrc: [
"'self'",
"unsafe-inline",
"'sha256-eE1k/Cs1U0Li9/ihPPQ7jKIGDvR8fYw65VJw+txfifw='",
],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
},
reportOnly: false,
})
);
我还从我的一个组件中删除了内联样式,因为组件表现得很奇怪
<>
<Survey.Survey
json={json}
showCompletePage={false}
onComplete={(result) => onComplete(result)}
/>
<div className="show-results">
<button
className="btn-results"
onClick={() => setResultsDisplay(!resultsDisplay)}
>
{resultsDisplay ? "Hide Charts" : "Show Charts"}
</button>
{resultsDisplay && (
<div>
<Result id={id} title={title} />
</div>
)}
</div>
</>
而且有效。
在开发模式下一切正常。乍一看,应用程序在构建模式下是相同的(我在服务器端使用 express)。但是当我尝试刷新我的页面时(url 包含参数)我收到 只有
{
surveyString: "[{"type":"radiogroup","name":"Favorite Character?","title":"Favorite Character?","isRequired":true,"colCount":1,"choices":["Walt","Hank","Jesse","Mike"]},{"type":"radiogroup","name":"Favorite Actor?","title":"Favorite Actor?","isRequired":true,"colCount":1,"choices":["Aaron Paul","Bryan Cranston","Jonathan Banks"]}]",
surveyTitle: "Breaking Bad Survey"
}
这是从服务器发送的响应,这当然是我想要的,但不知何故应用程序没有合并它。
我在 Chrome 中收到的错误是
Not allowed to load local resource: view-source
在 Firefox 中,错误看起来有些不同
Content Security Policy: The page’s settings blocked the loading of a resource a ...resource link...
通过这些错误,我承认了有关内容安全策略、快递包如何克服它的一些基本方法等等……但那是另一回事,我希望我能在反应方面解决问题。
我很乐观,因为我在其他页面上的 href links 有相同的行为。当我用 LinkTo 应用程序替换 aHref 时,工作正常。
我点击link,在新页面上一切正常,直到我刷新。
link 是到 github 页: component which not survives refresh
function SingleSurvey(props) {
const [complete, setComplete] = useState(false);
const [voted, setVoted] = useState(false);
const [json, setJson] = useState({});
const [title, setTitle] = useState("");
const [resultsDisplay, setResultsDisplay] = useState(false);
const { id } = useParams();
useEffect(() => {
surveyServices.getSingle(id).then((res) => {
const stringQuestions = JSON.parse(res.surveyString);
setJson({ questions: stringQuestions });
setTitle(res.surveyTitle);
});
}, [id]);
useEffect(() => {
const checkItem = window.localStorage.getItem(`chartVoted-${id}`);
if (checkItem) {
setVoted(true);
}
// eslint-disable-next-line
}, []);
function onComplete(result) {
surveyServices.updateVotes({
data: result.data,
id,
});
window.localStorage.setItem(`chartVoted-${id}`, true);
setComplete(true);
setTimeout(() => {
window.location.reload();
}, 1100);
}
return (
<main className="survey-page">
{complete && <p className="survey-finished"></p>}
{!voted ? (
<>
<Survey.Survey
json={json}
showCompletePage={false}
onComplete={(result) => onComplete(result)}
/>
<div className="show-results">
<button
className="btn-results"
onClick={() => setResultsDisplay(!resultsDisplay)}
>
{resultsDisplay ? "Hide Charts" : "Show Charts"}
</button>
<div
className="visible-results"
style={{ display: resultsDisplay ? "" : "none" }}
>
<Result id={id} title={title} />
</div>
</div>
</>
) : (
<div className="just-results">
<Result id={id} title={title} />
</div>
)}
</main>
);
}
export default SingleSurvey;
<Router>
<Notification />
<Switch>
<Route exact path="/api/survey/single/:id" component={SingleSurvey} />
</Switch>
</Router>
ReactDOM 渲染,我使用的是基本的 redux
<Provider store={store}>
<App />
</Provider>,
app.use(express.static(path.join(__dirname, "build")));
app.use("/api/survey", surveyController);
app.use("/api/users", usersController);
app.use("/api/login", loginController);
app.get("/", function (req, res) {
app.get("/*", function (req, res) {
res.sendFile(path.join(__dirname, "build", "index.html"));
});
});
如果想直接看问题app is uploaded on heroku.
希望不要错过任何有价值的信息。有人知道如何解决令人难以置信的恼人问题吗?
您混淆了您的 API 路由和您的客户端路由,因此导致超载。
当 Web 浏览器访问网站时,它们会发出 GET 请求,这与您与 Express 服务器交互的方式完全相同。
您的问题是您通过将用户重定向到向您的服务器发出 GET 请求的服务器端点,不小心向您的服务器发出了 get 请求。
发生了什么事
Url 更改由
Link
组件触发(不在您提供的代码中React Router 匹配 URL 而不会触发 API 请求(这是单页网络应用程序的工作方式)
<Route exact path="/api/survey/single/:id" component={SingleSurvey} />
页面刷新 Express 匹配 URL 和 returns API 响应而不是 index.html
app.use("/api/survey", surveyController);
解决方案
- 将您的 client-side 路径更改为:
/client/survey
根据 Alex Mckay 的回答,我更改了路线位置
<Route
exact
path="/client/survey/single/:id"
component={SingleSurvey}
/>
然后修复我服务器端的内容安全策略错误。 这对我来说是一个全新的领域,所以我在控制台中跟踪错误并一一修复。 使用 [helmet-csp] 包是非常直观的过程。
app.use(
csp({
directives: {
defaultSrc: ["'self'"],
fontSrc: ["https://fonts.googleapis.com/", "https://fonts.gstatic.com"],
connectSrc: ["'self'", "http://localhost:3005"],
styleSrc: [
"'self'",
"'unsafe-inline'",
"https://surveyjs.azureedge.net/1.8.0/modern.css",
"https://fonts.googleapis.com",
"'sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU='",
"'sha256-OTeu7NEHDo6qutIWo0F2TmYrDhsKWCzrUgGoxxHGJ8o='",
],
imgSrc: ["'self'", "http://localhost:3005"],
scriptSrc: [
"'self'",
"unsafe-inline",
"'sha256-eE1k/Cs1U0Li9/ihPPQ7jKIGDvR8fYw65VJw+txfifw='",
],
objectSrc: ["'none'"],
upgradeInsecureRequests: [],
},
reportOnly: false,
})
);
我还从我的一个组件中删除了内联样式,因为组件表现得很奇怪
<>
<Survey.Survey
json={json}
showCompletePage={false}
onComplete={(result) => onComplete(result)}
/>
<div className="show-results">
<button
className="btn-results"
onClick={() => setResultsDisplay(!resultsDisplay)}
>
{resultsDisplay ? "Hide Charts" : "Show Charts"}
</button>
{resultsDisplay && (
<div>
<Result id={id} title={title} />
</div>
)}
</div>
</>
而且有效。