簡體   English   中英

為什么 select 沒有以 react-hook-form 列出 reset() 上的加載值?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM