所以我目前正在学习一门课程,现在我甚至检查了他的 GitHub,它是相同的。问题是,我的 Header.jsx 组件都没有渲染。这是我的 Header.jsx 代码:
这是检查过的页面,如你所见,它是空的:
最后是 App.jsx 页面,显示我已正确导入 Header.jsx。我完全按照教程操作了。
对此的任何看法都很好,已经困扰我好几天了。
我有一个包含子组件的父组件。
子级包含多个表单元素,以及它们的状态和验证它们的函数。
父级有一个表单按钮,单击该按钮时会调用子级中实现的验证函数。
问题是,当提交时从父进程调用该函数时,该函数无法“看到”状态变量的当前值(它看到的是初始值)。
但是,当从子进程调用该函数时,它可以按预期看到当前值。
以下是 Parent 的实现:
type ValidatorRunner = () => boolean;
const Parent = () => {
const [ childValidator, setChildValidator ] = useState<ValidatorRunner>();
function validateChild(): boolean {
if (childValidator) return childValidator();
else return false;
}
const doSubmit = async (e: SyntheticEvent) => {
e.preventDefault();
const formData = new FormData(e.target as HTMLFormElement);
const formJson = Object.fromEntries(formData.entries());
if (validateChild()) {
console.log("[Parent]: Good to send data:\n" + JSON.stringify(formJson));
} else {
console.log("[Parent]: Can't send data (data not valid)");
}
};
return (
<div>
<form onSubmit={ doSubmit }>
<div>Parent</div>
<div><Child validatorSetter={ setChildValidator }/></div>
<div><button type='submit'>Submit</button></div>
</form>
</div>
);
};
这是孩子:
interface ChildProps {
text?: string,
validatorSetter?: (validator: () => ValidatorRunner) => void
}
const Child = ({text, validatorSetter}: ChildProps) => {
const [ textValue, setTextValue] = useState(text ?? "");
const [ textFeedback, setTextFeedback] = useState("");
useEffect(() => {
if (validatorSetter) {
validatorSetter(() => validate);
};
}, [validatorSetter]);
const validate = (): boolean => {
console.log("[Child]: validate " + textValue);
let isValidText: boolean = validateText(textValue);
return isValidText;
}
const validateText = (data: string): boolean => {
if (data.length === 0) {
setTextFeedback("The text can't be empty");
return false;
}
else {
setTextFeedback("");
return true;
}
};
const doChange = (e: ChangeEvent<HTMLInputElement>) => {
setTextValue(e.target.value);
validateText(e.target.value);
};
return (
<div style={{ border: '1px solid' }}>
<label htmlFor="text">Text: </label>
<input id="text" name='text' type='text' maxLength={ 16 } onChange={ doChange } value={ textValue }/>
<button type="button" onClick={ validate }>?</button>
<label> { textFeedback } </label>
</div>
);
};
单击[?](在 Child 中)将调用Child.validate()
,它会按预期将 的当前值打印Child.textValue
到控制台。
单击[Submit](在 Parent 中)将调用Child.validate()
,它会打印 的初始值Child.textValue
。
我该如何实现?我尝试过其他解决方案useRef
,例如useImperativeHandle
、等等,但无法在这种情况下实现。
我的 expo react native 与 nativewind 项目有问题,当我将 expo SDK 从 51 升级到 52 并通过从应用商店下载的 expo 应用在实际设备 iPhone 12 pro 上测试该应用时,它通过以下命令成功构建 npx expo start -c
但显示以下错误
IOS 错误
(NOBRIDGE) LOG Bridgeless mode is enabled
(NOBRIDGE) ERROR Error: Exception in HostFunction: Unable to convert string to floating point value: "large"
This error is located at:
in RNSScreen (created by Animated(Anonymous))
in Animated(Anonymous)
in Suspender (created by Freeze)
in Suspense (created by Freeze)
in Freeze (created by DelayedFreeze)
in DelayedFreeze
in InnerScreen (created by Screen)
in Screen (created by MaybeScreen)
in MaybeScreen (created by CardStack)
in RNSScreenContainer (created by ScreenContainer)
in ScreenContainer (created by MaybeScreenContainer)
in MaybeScreenContainer (created by CardStack)
in RCTView (created by View)
in View (created by CssInterop.View)
in CssInterop.View (created by Animated(View))
in Animated(View) (created by Background)
in Background (created by CardStack)
in CardStack (created by HeaderShownContext)
in RNCSafeAreaProvider (created by SafeAreaProvider)
in SafeAreaProvider (created by SafeAreaProviderCompat)
in SafeAreaProviderCompat (created by StackView)
in RCTView (created by View)
in View (created by CssInterop.View)
in CssInterop.View (created by GestureHandlerRootView)
in GestureHandlerRootView (created by StackView)
in StackView (created by StackNavigator)
in PreventRemoveProvider (created by NavigationContent)
in NavigationContent
in Unknown (created by StackNavigator)
in StackNavigator (created by RootNavigator)
in RootNavigator (created by App)
in ThemeProvider
in EnsureSingleNavigator
in BaseNavigationContainer
in NavigationContainerInner (created by App)
in QueryClientProvider (created by App)
in I18nextProvider (created by App)
in ThemeProvider (created by App)
in RCTView (created by View)
in View (created by CssInterop.View)
in CssInterop.View (created by App)
in RCTView (created by View)
in View (created by CssInterop.View)
in CssInterop.View (created by GestureHandlerRootView)
in GestureHandlerRootView (created by App)
in App (created by withDevTools(App))
in withDevTools(App)
in RCTView (created by View)
in View (created by CssInterop.View)
in CssInterop.View (created by AppContainer)
in RCTView (created by View)
in View (created by CssInterop.View)
in CssInterop.View (created by AppContainer)
in AppContainer
in main(RootComponent)
Android 错误
(NOBRIDGE) LOG Bridgeless mode is enabled
(NOBRIDGE) ERROR Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'RNCWebView' could not be found. Verify that a module by this name is registered in the native binary.Bridgeless mode: true. TurboModule interop: true. Modules loaded: {"NativeModules":[],"TurboModules":["PlatformConstants","LogBox","SourceCode","Appearance","AppState","AccessibilityInfo","DeviceInfo","BlobModule","WebSocketModule","DevSettings","DevToolsSettingsManager","Networking","DevLoadingView","ImageLoader","SoundManager","IntentAndroid","DeviceEventManager","NativeReactNativeFeatureFlagsCxx","NativeAnimatedModule","ReanimatedModule","RNGestureHandlerModule","StatusBarManager","StatusBarManager","I18nManager","RNCAsyncStorage"],"NotFound":["NativePerformanceCxx","NativePerformanceObserverCxx","AccessibilityManager","RedBox","BugReporting","HeadlessJsTaskSupport","LinkingManager","RNCSafeAreaContext","FrameRateLogger","KeyboardObserver","RNSModule","PlatformLocalStorage","RNC_AsyncSQLiteDBStorage","RNCWebView"]}
(NOBRIDGE) WARN 🚨 React Native's New Architecture is always enabled in Expo Go, but it is not explicitly enabled your project app config. This may lead to unexpected behavior when you create a production or development build. Set "newArchEnabled": true in your app.json.
Learn more: https://docs.expo.dev/guides/new-architecture/
如何修复上述错误,谨致问候。
我尝试升级所有库并从干净的构建开始,但错误在 Android 和 IOS 上仍然出现相同的情况。
我期望它能起作用:
interface Point {
x: number;
y: number;
}
function A({x, y}: Point = {x: 1, y: 1}) {
return `x:${x}y:${y}`;
}
export default function App() {
return <A/>; //error TS2739
}
export default function App() {
return <>{A()}</>; //ok, no problem
}
为什么它不起作用?
ps. Stackoverflow 要求我添加一些详细信息,但我做不到,因为代码很好地解释了问题。这就是我添加此 ps 的原因。
我找到了一个名为 nprogress 的库,它可以自动在我的 React 应用程序中显示全局进度条。为此,我需要在导航时进行监听。我从 react-router-dom 中找到了钩子 useNavigation ,它必须在RouterProvider中使用,但 id 不支持子项。我尝试这样做:
import { useEffect } from "react";
import "./App.css";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import HomePage from './HomePage.tsx',
import AboutPage from './AboutPage.tsx'
import {
Route,
Link,
useNavigation,
createBrowserRouter,
createRoutesFromElements,
RouterProvider,
} from "react-router-dom";
const ProgressBarHandler = () => {
const navigation = useNavigation();
useEffect(() => {
if (navigation.state === "loading") {
NProgress.start();
} else {
NProgress.done();
}
}, [navigation.state]);
return null;
};
const router = createBrowserRouter(
createRoutesFromElements(
<>
<Route path="/" element={<HomePage />} />
<Route path="/about" element={<AboutPage />} />
</>
)
);
function App() {
return (
<RouterProvider
router={router}
future={{
v7_startTransition: true,
}}
fallbackElement={<ProgressBarHandler />}
/>
);
}
我需要的是让它在导航时启动,因为有时需要几秒钟才能完成渲染一个复杂的页面,并在完成后停止。我发现这useNavigation
真的很酷,因为它还可以自动管理表单操作和许多其他事情。
您对如何使用此钩子或其他钩子来监控导航有什么建议吗?
经典示例,并不清楚为什么具有直接值的 setter 不起作用 setCount(count+1) 应用程序仅包含 1 并停止计数,但是每秒都会调用间隔函数,如果我们放置日志,我们就可以看到它。
const { useState, useEffect } = React;
const Counter = () => {
const [count, setCount] = useState(0);
useEffect(() => {
const id = setInterval(() => setCount(count+1), 1000);
// this set count works
// const id = setInterval(() => setCount(c => c + 1), 1000);
return () => clearInterval(id);
}, []);
return (<div>{count}<button onClick={()=>setCount(10)}>Give10</button></div>);
};
ReactDOM
.createRoot(root)
.render(<Counter/ >);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.3.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.3.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
当我尝试从 React 向我的节点服务器发出请求时出现此错误,尽管我启用了 cors,但我不明白为什么。
网络选项卡中的错误消息:
反应 axios 请求:
try {
const url = "http://192.168.178.112:8080/api/users";
const { data: res } = await axios.post(url, data);
navigate("/login");
console.log(res.message);
} catch (error) {
if (
error.response &&
error.response.status >= 400 &&
error.response.status <= 500
)
setError(error.response.data.message);
}
节点js表达:
require("dotenv").config();
const express = require("express");
const app = express();
const cors = require("cors");
const connection = require("./db");
const userRoutes = require("./routes/users");
const authRoutes = require("./routes/auth");
connection();
app.use(express.json());
app.use(cors());
app.use("/api/users", userRoutes);
app.use("/api/auth", authRoutes);
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`Server is running on http://localhost:${port}`);
});
我正在尝试在 json-server 文件中添加一些数据。为此,我使用了钩子表单,并使用 useMutation 发布数据。我能够添加 json-server 文件,但问题是,成功插入后,页面会自动重新加载。我想在成功后导航到另一个页面,但无法这样做。您能指导我这样做并停止刷新吗?代码是:
CreateUser.jsx 页面
import CommonForm from "../components/commonform";
import { useMutation } from "react-query";
const addUser = async (data) => {
let res = await axios.post("http://localhost:1000/user", data);
return res;
};
const CreateUser = () => {
const { mutate } = useMutation(addUser);
const submitHandler = (data) => {
console.log("Data submitted from the form", data);
mutate(data);
};
return (
<div>
<CommonForm view="createForm" submitHandler={submitHandler} />
</div>
);
};
export default CreateUser;
CommonForm.jsx
import { useForm } from "react-hook-form";
const CommonForm = ({ view, submitHandler }) => {
const { register, handleSubmit, formState } = useForm();
const { errors } = formState;
return (
<div>
<form onSubmit={handleSubmit(submitHandler)} noValidate>
{/* username field with validation */}
<label htmlFor="uname">User Name: </label>
<input
type="text"
id="uname"
{...register("username", {
required: {
value: true,
message: "* User name is required",
},
minLength: {
value: 3,
message: "Minimum length 3",
},
})}
autoComplete="off"
/>
{/* username validation message */}
<br />
<p>{errors.username?.message}</p>
<br />
{/* email field with validation */}
<label htmlFor="email">Email : </label>
<input
type="email"
id="email"
{...register("email", {
required: {
value: true,
message: "* email is required",
}
})}
autoComplete="off"
/>
{/* error validation message */}
<br />
<p>{errors.email?.message}</p>
<br />
<input type="submit" value="Submit" />
</form>
</div>
);
};
export default CommonForm;
db.json 文件:
{
"user": [
{
"id": "1",
"username": "John Doe",
"email": "[email protected]"
},
{
"id": "22f8",
"username": "hello",
"email": "[email protected]"
}
]
}
最后一条数据“Hello”是表单添加的。
当我尝试执行从属查询时遇到问题。
这是组件的代码,它仅使用 react-query 显示来自 API REST 的信息,即使将启用设置为 false,我也可以在浏览器上看到
浏览器工具:
GET https://localhost:7065/api/Location/cityById/undefined
[HTTP/2 400 226ms]
XHRGET
https://localhost:7065/api/Location/parishById/undefined
[HTTP/2 400 212ms]
XHRGET
https://localhost:7065/api/Location/townShipById/undefined
[HTTP/2 400 128ms]
XHRGET
https://localhost:7065/api/Location/zoneTypeById/undefined
[HTTP/2 400 181ms]
XHRGET
https://localhost:7065/api/Location/cityById/undefined
[HTTP/2 400 209ms]
XHRGET
https://localhost:7065/api/Location/parishById/undefined
[HTTP/2 400 155ms]
XHRGET
https://localhost:7065/api/Location/zoneTypeById/undefined
[HTTP/2 400 232ms]
XHRGET
https://localhost:7065/api/Location/townShipById/undefined
组件代码:
import { useQuery } from "@tanstack/react-query";
import { useRegisterFormViewContext } from "../providers/registerFormViewProvider";
import { useAuth } from "../hooks/useAuth";
import { GetStoreDetailService } from "../services/storeDetailService";
import { GetEstimateService } from "../services/estimateService";
import {
GetCityByIdService,
GetParishedByIdService,
GetStatesService,
GetTwonShipByIdService,
GetZoneTypesByIdService,
} from "../services/locationSerivce";
function ViewStoreDetail() {
const { storedValue } = useAuth();
const [state] = useRegisterFormViewContext();
const { data: viewDetailStore, isPending: isPendingViewDetailStore } =
useQuery({
queryKey: ["viewStoreDetail"],
queryFn: GetStoreDetailService(
storedValue,
state.select_store_id.select_store_id,
),
staleTime: 0,
enabled: true,
});
const { data: estimateData, isPending: isPendingEstimateData } = useQuery({
queryKey: ["viewStoreDetailEstimate"],
queryFn: GetEstimateService(storedValue),
staleTime: 0,
enabled: true,
});
const { data: states, isPending: isPendingStates } = useQuery({
queryKey: ["viewStoreDetailStates"],
queryFn: GetStatesService(storedValue),
staleTime: 0,
enabled: true,
});
const cityId = viewDetailStore?.std_dir_city_id;
const { data: city, isPending: isPendingCity } = useQuery({
enabled: false,
queryKey: ["viewStoreDetailCity", cityId],
queryFn: GetCityByIdService(storedValue, cityId),
staleTime: 0,
});
const parishedId = viewDetailStore?.std_dir_parroquia_id;
const { data: parished, isPending: isPendingParisged } = useQuery({
enabled: false,
queryKey: ["viewStoreDetailParished", parishedId],
queryFn: GetParishedByIdService(storedValue, parishedId),
staleTime: 0,
});
const townshipId = parished?.par_tow_id;
const { data: township, isPending: isPendingTownShip } = useQuery({
enabled: false,
queryKey: ["viewStoreDetailTownship", townshipId],
queryFn: GetTwonShipByIdService(storedValue, townshipId),
staleTime: 0,
});
const transportId = viewDetailStore?.std_dir_zone_type_id;
const { data: transportType, isPending: isPendingTransportType } = useQuery({
enabled: false,
queryKey: ["viewStoreDetailTransporType", transportId],
queryFn: GetZoneTypesByIdService(storedValue, transportId),
staleTime: 0,
});
return (
<div className="h-[calc(100vh-64px)] border-2 border-black">
SHOW information of the queries in the future...
</div>
);
}
export default ViewStoreDetail;
以下是我的 API 调用:
import { GetBaseUrl } from "./apiBaseUrl";
export async function GetStatesService(storedValue) {
try {
const response = await fetch(GetBaseUrl() + "api/Location/states", {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=UTF-8",
Authorization: `Bearer ${storedValue}`,
},
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
} catch (error) {
throw new Error("Obtener estados fallo: " + error.message);
}
}
export async function GetCitiesByStateService(storedValue, stateId) {
try {
const response = await fetch(
GetBaseUrl() + `api/Location/citiesByState/${stateId}`,
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=UTF-8",
Authorization: `Bearer ${storedValue}`,
},
},
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
} catch (error) {
throw new Error("Obtener ciudades fallo: " + error.message);
}
}
export async function GetCityByIdService(storedValue, cityId) {
try {
const response = await fetch(
GetBaseUrl() + `api/Location/cityById/${cityId}`,
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=UTF-8",
Authorization: `Bearer ${storedValue}`,
},
},
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
} catch (error) {
throw new Error("Obtene ciudad fallo: " + error.message);
}
}
export async function GetTwonShipsByStateService(storedValue, stateId) {
try {
const response = await fetch(
GetBaseUrl() + `api/Location/townShipsByState/${stateId}`,
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=UTF-8",
Authorization: `Bearer ${storedValue}`,
},
},
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
} catch (error) {
throw new Error("Obtener municipios fallo: " + error.message);
}
}
export async function GetTwonShipByIdService(storedValue, twonShipId) {
try {
const response = await fetch(
GetBaseUrl() + `api/Location/townShipById/${twonShipId}`,
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=UTF-8",
Authorization: `Bearer ${storedValue}`,
},
},
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
} catch (error) {
throw new Error("Obtene municipio fallo: " + error.message);
}
}
export async function GetParishedByTownShipService(storedValue, townShipId) {
try {
const response = await fetch(
GetBaseUrl() + `api/Location/parishesByTownShip/${townShipId}`,
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=UTF-8",
Authorization: `Bearer ${storedValue}`,
},
},
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
} catch (error) {
throw new Error("Obtener parroquias fallo: " + error.message);
}
}
export async function GetParishedByIdService(storedValue, parishedId) {
try {
const response = await fetch(
GetBaseUrl() + `api/Location/parishById/${parishedId}`,
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=UTF-8",
Authorization: `Bearer ${storedValue}`,
},
},
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
} catch (error) {
throw new Error("Obtene parroquia fallo: " + error.message);
}
}
export async function GetZoneTypesService(storedValue) {
try {
const response = await fetch(GetBaseUrl() + "api/Location/zoneTypes", {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=UTF-8",
Authorization: `Bearer ${storedValue}`,
},
});
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
} catch (error) {
throw new Error("Obtener tipos de zonas fallo: " + error.message);
}
}
export async function GetZoneTypesByIdService(storedValue, zoneTypeId) {
try {
const response = await fetch(
GetBaseUrl() + `api/Location/zoneTypeById/${zoneTypeId}`,
{
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json; charset=UTF-8",
Authorization: `Bearer ${storedValue}`,
},
},
);
if (!response.ok) {
throw new Error("Network response was not ok");
}
return response.json();
} catch (error) {
throw new Error("Obtener tipo de zona fallo: " + error.message);
}
}
这是我的App.jsx
:
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import Homepage from "./pages/Homepage";
import Login from "./pages/Login";
import EmptyLayaout from "./layaout/EmptyLayaout";
import AppLayaout from "./layaout/AppLayaout";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { AuthProvider } from "./hooks/useAuth";
import PrivateRoute from "./pages/PrivateRoute";
import Users from "./pages/Users";
import "react-toastify/dist/ReactToastify.css";
import { ToastContainer } from "react-toastify";
import ViewStoreDetail from "./pages/ViewStoreDetail";
import UpdateStoreDetail from "./pages/UpdateStoreDetail";
import SelectViewStoreDetail from "./pages/SelectViewStoreDetail";
import RegisterFormViewProvider from "./providers/registerFormViewProvider";
const queryClient = new QueryClient({
defaultOptions: {
queries: {
staleTime: 60 * 1000,
enabled: false,
},
},
});
const router = createBrowserRouter([
{
element: <EmptyLayaout />,
children: [
{
path: "/login",
element: <Login />,
},
],
},
{
element: <AppLayaout />,
children: [
{
path: "/",
element: (
<PrivateRoute redirectTo="/login">
<Homepage />
</PrivateRoute>
),
},
{
path: "/view-store",
element: (
<PrivateRoute redirectTo="/login">
<SelectViewStoreDetail />
</PrivateRoute>
),
},
{
path: "/view-store-detail-resume",
element: (
<PrivateRoute redirectTo="/login">
<ViewStoreDetail />
</PrivateRoute>
),
},
{
path: "/update-store",
element: (
<PrivateRoute redirectTo="/login">
<UpdateStoreDetail />
</PrivateRoute>
),
},
{
path: "/users",
element: (
<PrivateRoute redirectTo="/login">
<Users />
</PrivateRoute>
),
},
],
},
]);
function App() {
return (
<RegisterFormViewProvider>
<AuthProvider>
<ToastContainer />
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} position="right" />
<RouterProvider router={router} />
</QueryClientProvider>
</AuthProvider>
</RegisterFormViewProvider>
);
}
export default App;
我不知道为什么如果启用设置为 false 它会继续触发查询
我的 api 在任何地方都运行良好,除了当我尝试执行 if 块以解决潜在的 Axios 错误时。这是因为status
在 中使用了 isresponse.response.status
而不是response.status
typescript 会抛出错误Property 'response' does not exist on type 'AxiosResponse<any, any>'.
有人能帮我吗?
在没有 AxiosError 的情况下工作:
postBoundary: async (boundary: CreateBoundary) => {
const response = await axios.post(
`${config.baseApiPath}boundary`,
boundary
);
return response.data; //returns correctly
}
无法使用 Axios 出现错误:
postBoundary: async (boundary: CreateBoundary) => {
const response = await axios.post(
`${config.baseApiPath}boundary`,
boundary
);
// when response has an Axios error response.status
// doesn't exist because there are two nested responses
if (response.response.status ===
HttpStatusCode.PayloadTooLarge) {
throw new Error("Error");
}
return response.data;
}