我有两个文件Profile.js和Controller.js如下。当我访问链接localhost/profile时,我看到两个额外的POST请求从前端发送到后端。
在进一步的调试中,我发现,当我访问localhost/profile链接时,Controller.js文件中的useEffect钩子正在执行。这是正常的还是我在这里做错了什么?
注意请不要关闭这个问题,这和useEffect被调用两次是不一样的,useEffect在同一个组件内被调用两次是一回事,这里执行的是其他组件的useEffect,这两者本质上是不同的。
最后,我展示了这些组件是如何包含在App.js文件中的。
Profile.js
import react, { useState, useEffect } from "react";
import axios from "axios";
const lm = require("./lm.js");
const Profile = () => {
const [firstName, setFirstName] = useState(null);
const [lastName, setLastName] = useState(null);
const [email, setEmail] = useState(null);
const [skype, setSkype] = useState(null);
const [mobile, setMobile] = useState(null);
const [dob, setDob] = useState(null);
const [created, setCreated] = useState(null);
const [gender, setGender] = useState(null);
const fetchProfile = async () => {
var user = null;
const userData = localStorage.getItem("user");
if (userData) {
user = JSON.parse(userData);
try {
await axios
.post(
"/profile",
{ email: user.email },
{
headers: {
Authorization: user.jwt,
},
},
)
.then(function (res) {
let obj = JSON.parse(res.data);
setFirstName(obj.firstname);
setLastName(obj.lastname);
setMobile(obj.mobile);
setEmail(obj.email);
setSkype(obj.skype);
setDob(new Date(obj.dob).toLocaleDateString());
setCreated(new Date(obj.created).toLocaleDateString());
setGender(lm.getGender(obj.gender));
});
} catch (err) {
console.log(err);
window.location.href = "/authrequired";
}
} else {
console.log("User not logged in");
}
};
useEffect(() => {
fetchProfile();
}, []);
return (
<div className="medium-text">
<div className="center">
<h2>User profile</h2>
<table id="tbl">
<tbody>
<tr>
<th>Fields</th>
<th>Values</th>
</tr>
{firstName && (
<tr>
<td>First name</td>
<td>{firstName}</td>
</tr>
)}
{lastName && (
<tr>
<td>Last name</td>
<td>{lastName}</td>
</tr>
)}
{email && (
<tr>
<td>Email Id</td>
<td>{email}</td>
</tr>
)}
{mobile && (
<tr>
<td>Mobile</td>
<td>{mobile}</td>
</tr>
)}
{skype && (
<tr>
<td>Skype</td>
<td>{skype}</td>
</tr>
)}
{dob && (
<tr>
<td>Date of birth</td>
<td>{dob}</td>
</tr>
)}
{created && (
<tr>
<td>Created on</td>
<td>{created}</td>
</tr>
)}
{gender && (
<tr>
<td>Gender</td>
<td>{gender}</td>
</tr>
)}
</tbody>
</table>
</div>
</div>
);
};
export default Profile;
字符串
Controller.js
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import { Link } from "react-router-dom";
import axios from "axios";
const lm = require("../../routes/lm.js");
const AddController = () => {
const [status, setStatus] = useState(null);
const handleSubmit = async (
name,
ipaddr,
port,
sshuser,
sshpass,
sshport,
license,
) => {
setStatus(null);
const userData = localStorage.getItem("user");
if (userData != null) {
var user = JSON.parse(userData);
try {
const res = await axios
.post(
"/exec/addcontroller",
{
email: user.email,
name,
ipaddr,
port,
sshuser,
sshpass,
sshport,
license,
},
{
headers: {
Authorization: user.jwt,
},
},
)
.then(function (res) {
if (res.status === 200) {
setStatus({
type: "success",
message: `Controller ${name} added successfully`,
});
} else {
setStatus({
type: "error",
message: `Could not add controller ${name}`,
});
}
});
} catch (err) {
setStatus({
type: "error",
message: err.message,
});
}
} else {
setStatus({
type: "error",
message: "User not logged in",
});
}
};
let out = (
<form
onSubmit={(event) => {
event.preventDefault();
const [name, ipaddr, port, sshuser, sshpass, sshport, license] =
event.target.elements;
handleSubmit(
name.value,
ipaddr.value,
port.value,
sshuser.value,
sshpass.value,
sshport.value,
license.value,
);
}}
>
<div className="medium-text">
<div className="center">
<h2>Add Controller</h2>
<table id="">
<tbody>
<tr>
<td>
<b>Controller</b>
<br />
<input
required
type="text"
maxLength={15}
id="name"
name="name"
placeholder="Unique name"
/>
</td>
<td>
<b>IP Address</b>
<br />
<input
required
type="text"
maxLength={32}
id="ipaddr"
name="ipaddr"
placeholder="Machine IP address"
/>
</td>
<td>
<b>Port</b>
<br />
<input
required
type="text"
maxLength={5}
id="port"
name="port"
placeholder="Listen port"
/>
</td>
</tr>
<tr>
<td>
<b>SSH User</b>
<br />
<input
required
type="text"
maxLength={15}
id="sshuser"
name="sshuser"
placeholder="Machine SSH user"
/>
</td>
<td>
<b>SSH Password</b>
<br />
<input
required
type="password"
maxLength={15}
id="sshpass"
name="sshpass"
autoComplete="on"
placeholder="Machine SSH password"
/>
</td>
<td>
<b>SSH Port</b>
<br />
<input
required
type="text"
maxLength={5}
id="sshport"
name="sshport"
placeholder="SSH Listen port"
/>
</td>
</tr>
</tbody>
</table>
<table id="">
<tbody>
<tr>
<td>
<b>License</b>
<br />
<input
required
type="text"
maxLength={24}
id="license"
name="license"
placeholder="License file name"
/>
</td>
</tr>
</tbody>
</table>
<br />
<div className="">
<button type="submit">Submit</button>
</div>
<br />
{status && (
<div className={`alert ${status.type}`}>{status.message}</div>
)}
</div>
</div>
</form>
);
return out;
};
const EditOneController = () => {
const initState = [
{ name: "", ipaddr: "", port: 0, sshuser: "", sshport: 0, license: "" },
];
const [state, setState] = useState(initState);
const [status, setStatus] = useState(null);
var user = null;
const userData = localStorage.getItem("user");
if (userData != null) {
user = JSON.parse(userData);
}
const handleSubmit = async (
name,
ipaddr,
port,
sshuser,
sshpass,
sshport,
license,
) => {
setStatus(null);
if (user != null) {
try {
const res = await axios
.post(
"/exec/editonecontroller",
{
email: user.email,
name,
ipaddr,
port,
sshuser,
sshpass,
sshport,
license,
},
{
headers: {
Authorization: user.jwt,
},
},
)
.then(function (res) {
if (res.status === 200) {
setStatus({
type: "success",
message: `Controller ${name} edited successfully`,
});
} else {
setStatus({
type: "error",
message: `Could not edit controller ${name}`,
});
}
});
} catch (err) {
console.log(err);
setStatus({
type: "error",
message: err.message,
});
}
} else {
setStatus({
type: "error",
message: "User not logged in",
});
}
};
const name = lm.getURLQueryVariable("name");
const fetchController = async () => {
try {
await axios
.post(
"/editonecontroller/data/?name=" + name,
{ email: user.email },
{
headers: {
Authorization: user.jwt,
},
},
)
.then(function (res) {
//console.log(res);
if (res.status === 200) {
const newState = res.data.flatMap(
({ name, ipaddr, port, sshuser, sshpass, sshport, license }) => [
{ name, ipaddr, port },
{ sshuser, sshpass, sshport },
{ license },
],
);
setState(newState);
} else {
setStatus({
type: "error",
message: `Could not fetch controller ${name} data`,
});
}
});
} catch (err) {
setStatus({
type: "error",
message: err.message,
});
}
};
useEffect(() => {
fetchController();
}, []);
const labelArr = [
"Controller",
"IP Address",
"Port",
"SSH User",
"SSH Password",
"SSH Port",
"License",
];
var labelIndex = 0;
let out = (
<form
onSubmit={(event) => {
event.preventDefault();
const [name, ipaddr, port, sshuser, sshpass, sshport, license] =
event.target.elements;
handleSubmit(
name.value,
ipaddr.value,
port.value,
sshuser.value,
sshpass.value,
sshport.value,
license.value,
);
}}
>
<div className="medium-text">
<div className="center">
<h2>Edit Controller</h2>
<table id="">
<tbody>
{state.map((item, index1) => (
<tr key={index1}>
{Object.keys(item).map((key, index2) => (
<td key={labelIndex++}>
<b>{labelArr[labelIndex]}</b>
<br />
<input
required
type={labelIndex == 4 ? "password" : "text"}
id={key}
name={key}
onChange={(e) => {}}
defaultValue={item[key]}
/>
</td>
))}
</tr>
))}
</tbody>
</table>
<br />
<div className="">
<button type="submit">Submit</button>
</div>
<br />
{status && (
<div className={`alert ${status.type}`}>{status.message}</div>
)}
</div>
</div>
</form>
);
return out;
};
const EditController = () => {
const initState = [
{ name: "", ipaddr: "", port: 0, sshuser: "", sshport: 0, license: "" },
];
const [state, setState] = useState(initState);
const [status, setStatus] = useState(null);
var user = null;
const userData = localStorage.getItem("user");
if (userData != null) {
user = JSON.parse(userData);
}
const fetchControllers = async () => {
setStatus(null);
if (user != null) {
try {
const res = await axios
.post(
"/exec/editcontroller",
{ email: user.email },
{
headers: {
Authorization: user.jwt,
},
},
)
.then(function (res) {
if (res.status === 200) {
setState(res.data);
} else {
setStatus({
type: "error",
message: "Error in displaying data",
});
}
});
} catch (err) {
setStatus({
type: "error",
message: err.message,
});
}
} else {
setStatus({
type: "error",
message: "User not logged in",
});
}
};
useEffect(() => {
fetchControllers();
}, []);
function editSingleControllerLink(val) {
return "/components/editonecontroller?name=" + val.val;
}
return (
<div className="medium-text">
<div className="center">
<h2>Controllers</h2>
<table id="tbl">
<thead>
<tr>
<th>Name</th>
<th>IP Address</th>
<th>Port</th>
<th>SSH User</th>
<th>SSH Port</th>
<th>License</th>
</tr>
</thead>
<tbody>
{state.map((item, index) => (
<tr key={index}>
{Object.values(item).map((val, index) =>
index === 0 ? (
<td key={index}>
{" "}
<a href={editSingleControllerLink({ val })}>{val}</a>{" "}
</td>
) : (
<td key={index}>{val}</td>
),
)}
</tr>
))}
</tbody>
</table>
<br />
{status && (
<div className={`alert ${status.type}`}>{status.message}</div>
)}
</div>
</div>
);
};
export default { AddController, EditController, EditOneController };
型
这些组件包含在App.js文件中,如下所示。
import { Routes, Route } from 'react-router-dom';
import Home from '../routes/Home';
import Login from '../routes/Login';
import Register from '../routes/Register';
import Profile from '../routes/Profile';
import Logout from '../routes/Logout';
import AuthReqd from '../routes/AuthReqd';
import controller from '../modules/controller/controller.js'
const App = () => {
return (
<>
<Routes>
<Route path="/" element={<Layout />}>
<Route index element={<Home />} />
<Route path="components/addcontroller" element={controller.AddController()} />
<Route path="components/editcontroller" element={controller.EditController()} />
<Route path="components/editonecontroller" element={controller.EditOneController()} />
<Route path="login" element={<Login />} />
<Route path="register" element={<Register />} />
<Route path="profile" element={<Profile />} />
<Route path="logout" element={<Logout />} />
<Route path="authrequired" element={<AuthReqd />} />
<Route path="*" element={<p>Not found!</p>} />
</Route>
</Routes>
</>
);
};
export default App;
型
2条答案
按热度按时间carvr3hs1#
Controller.js
中的这一行有问题字符串
您要将多个组件导出为单个对象,这需要使用以下导入
型
我只能假设你会用以下的用法
型
在将它们作为函数调用时,您将立即执行其中的代码。
而应使用命名导出
型
和JSX元素
型
vddsk6oq2#
有人说,你出口组件的方式是一个问题,但实际上并不重要。
字符串
你唯一的问题是
型
与下面的自执行函数示例等效:
型
如果我们打开这些自执行函数,我们得到:
型
一个可以帮助你避免这些错误的技巧是,你的React函数组件不应该被你执行,而应该只用于创建JSX元素。
型
切换到JSX,您的代码应该如下所示
型