我试图将输入地址自动填充合并到模态中。出现自动填充建议,但是当我尝试单击/选择首选地址时,发生错误并且模式关闭。我手动编码了模式。没有使用样式库。
这是我的模态代码:
import { cloneElement, createContext, useContext, useState } from 'react';
import { useClickOutside } from '../hooks/useClickOutside';
import { createPortal } from 'react-dom';
import { HiXMark } from 'react-icons/hi2';
const ModalContext = createContext();
function Modal({ children }) {
const [openName, setOpenName] = useState('');
const close = () => setOpenName('');
const open = setOpenName;
return (
<ModalContext.Provider value={{ openName, close, open }}>
{children}
</ModalContext.Provider>
);
}
function Open({ children, opens: opensWindowName }) {
const { open } = useContext(ModalContext);
// return cloneElement(children, { onClicsk: () => console.log('oyeah') });
return cloneElement(children, { onClick: () => open(opensWindowName) });
}
function Window({ children, name }) {
const { openName, close } = useContext(ModalContext);
const ref = useClickOutside(close);
if (name !== openName) return null;
// createPortal set the element to the desired parent element
return createPortal(
<div className="fixed left-0 top-0 z-[1000] h-full w-full backdrop-blur-sm transition-all">
<div
className="fixed left-[50%] top-[50%] -translate-x-1/2 -translate-y-1/2 rounded-md bg-grey-0 px-8 py-6 shadow-lg transition-all"
ref={ref}
>
<button className="absolute right-1 top-1 translate-x-px translate-y-px rounded-md p-1 text-grey-500 transition-all hover:bg-grey-100">
<HiXMark onClick={close} className="h-6 w-6" />
</button>
{cloneElement(children, { onCloseModal: close })}
</div>
</div>,
document.body,
);
}
Modal.Open = Open;
Modal.Window = Window;
export default Modal;
这是我的创建部署代码:
import { useForm } from 'react-hook-form';
import FormRow from '../../ui/FormRow';
import { useCreateDeployment } from './useCreateDeployment';
import { useEditDeployment } from './useEditDeployment';
import { DayPicker, getDefaultClassNames } from 'react-day-picker';
import { useEffect, useState } from 'react';
import { add } from 'date-fns';
import 'react-day-picker/dist/style.css';
import { AddressAutofill } from '@mapbox/search-js-react';
function CreateDeployment({ deploymentToEdit = {}, onCloseModal }) {
const [selected, setSelected] = useState({ from: undefined, to: undefined });
const maxDate = add(new Date(), { years: 1 });
const { from: fromDate, to: toDate } = selected;
// console.log(deploymentToEdit);
const handleSelect = (selectedRange) => {
if (selectedRange === undefined) return;
setSelected(selectedRange);
};
const { isCreating, createDeployment } = useCreateDeployment();
const { isEditing, editDeployment } = useEditDeployment();
const isWorking = isCreating || isEditing;
const { deploymentId: editId, ...editValues } = deploymentToEdit;
const isEditSession = Boolean(editId);
const { register, handleSubmit, reset, formState } = useForm({
defaultValues: isEditSession ? editValues : {},
});
const { errors } = formState;
const defaultClassNames = getDefaultClassNames();
function onSubmit(data) {
// console.log(data);
if (isEditSession)
editDeployment(
{
newDeploymentData: { ...data },
deploymentId: editId,
},
{ onSuccess: (data) => reset() },
onCloseModal?.(),
);
else
createDeployment(
{ ...data, startDate: selected.from, endDate: selected.to },
{ onSuccess: (data) => reset() },
onCloseModal?.(),
);
}
return (
<form
className="max-h-100 w-[40rem] text-lg"
onSubmit={handleSubmit(onSubmit)}
>
<div className="max-h-[40rem] overflow-y-auto">
<FormRow
label="Deployment Name"
error={errors?.deploymentName?.message}
>
<input
className="rounded-md border border-solid border-grey-300 bg-grey-0 px-4 py-2 shadow-sm"
{...register('deploymentName', {
required: 'This field is required',
})}
disabled={isWorking}
/>
</FormRow>
<FormRow
label="Number of Personnel"
error={errors?.numberOfPersonnel?.message}
>
<input
className="rounded-md border border-solid border-grey-300 bg-grey-0 px-4 py-2"
{...register('numberOfPersonnel', {
required: 'This field is required',
})}
/>
</FormRow>
<FormRow
label="Number of Resources"
error={errors?.numberOfResources?.message}
>
<input
className="rounded-md border border-solid border-grey-300 bg-grey-0 px-4 py-2"
{...register('numberOfResources', {
required: 'This field is required',
})}
disabled={isWorking}
/>
</FormRow>
<FormRow label="Location" error={errors?.location?.message}>
{/* <input
className="rounded-md border border-solid border-grey-300 bg-grey-0 px-4 py-2"
{...register('location', {
required: 'This field is required',
})}
disabled={isWorking}
/> */}
<AddressAutofill accessToken="Token">
<input
className="rounded-md border border-solid border-grey-300 bg-grey-0 px-4 py-2"
// name="address-1"
// autoComplete="address-line1"
/>
</AddressAutofill>
</FormRow>
<div className="flex flex-col items-center border-b border-grey-100 pt-4">
<div className="m-auto flex">
<p className="mx-10 px-4 text-sm font-medium text-grey-700">
From Date:{' '}
{fromDate ? fromDate.toLocaleDateString() : 'Not selected'}
</p>
<p className="mx-10 px-10 text-sm font-medium text-grey-700">
End Date: {toDate ? toDate.toLocaleDateString() : 'Not selected'}
</p>
</div>
<DayPicker
classNames={{
root: `${defaultClassNames.root} scale-75 text-base font-medium text-grey-700 `,
months: `flex gap-10`,
range_start: `rounded-full bg-brand-500 opacity-2- text-grey-200`,
range_end: `rounded-full bg-brand-500 opacity-2- text-grey-200`,
today: `font-bold text-brand-500`,
selected: `bg-brand-300 font-medium text-brand-200`,
chevron: `${defaultClassNames.chevron} fill-brand-500`,
}}
mode="range"
selected={selected}
onSelect={handleSelect}
startMonth={new Date()}
endMonth={maxDate}
captionLayout="dropdown-months"
numberOfMonths={2}
disabled={{
before: new Date(),
after: maxDate,
}}
/>
</div>
<FormRow label="Status" error={errors?.status?.message}>
<select
className="rounded-md border border-solid border-grey-300 bg-grey-0 px-4 py-2"
{...register('status', {
required: 'This field is required',
})}
disabled={isWorking}
>
<option value="Pending">Pending</option>
<option value="Ongoing">Ongoing</option>
</select>
</FormRow>
<FormRow label="OPR" error={errors?.opr?.message}>
<input
className="rounded-md border border-solid border-grey-300 bg-grey-0 px-4 py-2"
{...register('opr', {
required: 'This field is required',
})}
disabled={isWorking}
/>
</FormRow>
<FormRow
className="!bg-red-600"
label="Description"
error={errors?.description?.message}
>
<textarea
className="h-28 w-56 rounded-md border border-solid border-grey-300 bg-grey-0 px-4 py-2"
{...register('description', {
required: 'This field is required',
})}
disabled={isWorking}
/>
</FormRow>
<div className="flex justify-end">
<button
className="btn-secondary mx-2 mt-[auto]"
type="reset"
onClick={() => onCloseModal?.()}
disabled={isWorking}
>
Cancel
</button>
<button
type="submit"
className="btn-primary mx-2 mt-5"
disabled={isWorking}
>
Submit
</button>
</div>
</div>
</form>
);
}
export default CreateDeployment;
这是我每次尝试单击建议地址时遇到的错误:
我已经在 Createeployment 组件中直接测试了自动填充功能,并且它可以工作,因此仅当在模态模式中使用 Createdeployment 时。
name
和 autoComplete
属性。取消注释这些属性可以解决问题。
<AddressAutofill accessToken="Token">
<input
className="rounded-md border border-solid border-grey-300 bg-grey-0 px-4 py-2"
name="address-1"
autoComplete="address-line1"
/>
</AddressAutofill>