[英]Why aren't select lists loading values on reset() in react-hook-form?
此表單作為常規表單正常工作 - 提交保留下拉值。 當我使用 RHF 的reset()
從 URL 參數加載數據時,輸入框顯示默認值,但 select 字段不反映默認值。
我在這里要實現的功能是從 URL 查詢字符串參數中加載值,如下所示:
http://localhost:3000/search?search=dev&location=&environment=On-Site&job_type=Internship&industry=&industry_category=&date_posted=&offset=0&count=25
...有效地使其“無狀態”,因此我們能夠將此 URL 傳遞給任何人,它會加載表單值、執行搜索等。
import React, { useContext, useEffect, useState, useRef } from "react";
import { useForm, Controller } from "react-hook-form";
import InputMask from "react-input-mask";
import useLookupService from "../../service/lookup_service";
const Search = props => {
const { onSearch } = props;
const lookupSvc = useLookupService();
const [searchFormDefaults, setSearchFormDefaults] = useState(null);
const [locationOptions, setLocationOptions] = useState([]);
const [jobTypeOptions, setJobTypeOptions] = useState([]);
const [workEnvironmentOptions, setWorkEnvironmentOptions] = useState([]);
const [industryOptions, setIndustryOptions] = useState([]);
const [industryCategoryOptions, setIndustryCategoryOptions] = useState([]);
const {
register,
setValue,
handleSubmit,
control,
reset,
formState: { errors }
} = useForm({
defaultValues: searchFormDefaults,
context: JobSearchForm.type,
resolver: validator.validateResolver
});
useEffect(() => {
loadData();
}, []);
useEffect(() => {
if (!window.location.search) {
return;
}
const queryParams = new URLSearchParams(window.location.search);
let defaults = Object.fromEntries(queryParams);
setSearchFormDefaults(defaults);
reset(defaults);
}, [reset]);
const loadData = async () => {
let [
jobTypesData,
workEnvironmentsData,
industriesData,
industryCategoriesData
] = await Promise.all([
lookupSvc.getJobTypes(),
lookupSvc.getWorkEnvironments(),
lookupSvc.getIndustries(),
lookupSvc.getIndustryCategories()
]);
setJobTypeOptions([
<option key={-1} value="">Please select...</option>,
jobTypesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setWorkEnvironmentOptions([
<option key={-1} value="">Please select...</option>,
workEnvironmentsData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIndustryOptions([
<option key={-1} value="">Please select...</option>,
industriesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIndustryCategoryOptions([
<option key={-1} value="">Please select...</option>,
industryCategoriesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
};
return (
<div>
<div>
<div>
Filters
</div>
<div>
<a onClick={onClearClick}>
Clear Filters
</a>
</div>
</div>
<form onSubmit={handleSubmit(onSearch)} autoComplete="off">
<div>
<div>
<div>
<label>Search</label>
</div>
<input type="text" {...register("search")} />
{errors.search && <span className="validation">{errors.search}</span>}
</div>
<div>
<div>
<label>Location</label>
</div>
<input type="text" {...register("location")} onChange={onLocationChange} />
{errors.location && <span className="validation">{errors.location}</span>}
</div>
<div>
<div>
<label>Work Environment</label>
</div>
<select {...register("environment")}>
{workEnvironmentOptions}
</select>
</div>
<div>
<div>
<label>Date Posted</label>
</div>
<Controller
control={control}
name="date_posted"
render={({ field }) => (
<InputMask {...field} mask="99/99/9999" />
)}
/>
{errors.date_posted && <span className="validation">{errors.date_posted}</span>}
</div>
<div>
<div>
<label>Job Type</label>
</div>
<select {...register("job_type")}>
{jobTypeOptions}
</select>
</div>
<div>
<div>
<label>Job Industry</label>
</div>
<select {...register("industry")}>
{industryOptions}
</select>
</div>
<div>
<div>
<label>Industry Category</label>
</div>
<select {...register("industry_category")}>
{industryCategoryOptions}
</select>
</div>
<button type="submit">
Search
</button>
</div>
</form>
</div>
);
};
export default Search;
請注意,所選值和顯示值設置為相同 - 一個字符串,例如“On-Site”。
在調試時,第一個useEffect()
在第二個之前觸發並加載數據,並以 reset 作為其參數。 我想也許列表正在重新加載並清除選定的值,但我沒有看到這方面的證據。
在組件的return
行設置斷點時, searchFormDefaults
包含預期值,但它們始終設置為屏幕上的默認值(初始“請 select...”創建時。)
這是我在最終渲染中看到的searchFormDefaults
:
{
"search": "dev",
"location": "",
"environment": "On-Site",
"job_type": "Internship",
"industry": "",
"industry_category": "",
"date_posted": "",
"offset": "0",
"count": "25"
}
我對 react-hook-form 還很陌生,所以我確定我做了一些愚蠢的事情,但我無法發現它或在任何地方找到解釋。
弄清楚了。 只是一個簡單標志解決的異步問題。
const [isDataLoaded, setIsDataLoaded] = useState(false);
...然后在我的數據加載 function 中:
const loadData = async () => {
let [
jobTypesData,
workEnvironmentsData,
industriesData,
industryCategoriesData
] = await Promise.all([
lookupSvc.getJobTypes(),
lookupSvc.getWorkEnvironments(),
lookupSvc.getIndustries(),
lookupSvc.getIndustryCategories()
]);
setJobTypeOptions([
<option key={-1} value="">Please select...</option>,
jobTypesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setWorkEnvironmentOptions([
<option key={-1} value="">Please select...</option>,
workEnvironmentsData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIndustryOptions([
<option key={-1} value="">Please select...</option>,
industriesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIndustryCategoryOptions([
<option key={-1} value="">Please select...</option>,
industryCategoriesData.map((x, i) => <option key={i} value={x.name}>{x.name}</option>)
]);
setIsDataLoaded(true);
};
...以及需要它的鈎子:
useEffect(() => {
if (!isDataLoaded) {
return;
}
if (!window.location.search) {
return;
}
const queryParams = new URLSearchParams(window.location.search);
let defaults = Object.fromEntries(queryParams);
setSearchFormDefaults(defaults);
reset(defaults);
}, [reset, isDataLoaded]);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.