我有一个编辑组件,应该用于我的数据库中的三个表。然而我遇到了
React Hook is called conditionally
。我想要条件挂钩,因为正在更新的表需要根据我正在编辑的数据进行更改。似乎唯一的选择是:像我下面的那样执行,这会给出钩子错误,或者将其分成三个单独的组件,这不利于制作可重用的反应组件。这可以做到吗?
import { useState, useEffect } from "react";
import { useParams, useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
import { TextField, FormControlLabel, Checkbox, FormGroup, Button } from "@mui/material";
import {
useAddAttractionMutation,
useFetchAttractionQuery,
useUpdateAttractionMutation,
useRemoveAttractionMutation,
useAddRestaurantMutation,
useFetchRestaurantQuery,
useUpdateRestaurantMutation,
useRemoveRestaurantMutation,
useAddShowMutation,
useFetchShowQuery,
useUpdateShowMutation,
useRemoveShowMutation,
} from "../store/apis/dappApi";
import Dropdown from "./Dropdown";
import { PARK_AREAS } from "../constants";
function Edit({ type }) {
const { id } = useParams();
const navigate = useNavigate();
const parks = Object.keys(PARK_AREAS);
const [name, setName] = useState("");
const [park, setPark] = useState(parks[0]);
const [area, setArea] = useState(PARK_AREAS[park][0]);
const [completed, setCompleted] = useState(false);
let mutationVariables;
if (type === "attractions") {
mutationVariables = {
addMutation: useAddAttractionMutation()[0],
updateMutation: useUpdateAttractionMutation()[0],
removeMutation: useRemoveAttractionMutation()[0],
fetchData: useFetchAttractionQuery(id),
};
} else if (type === "restaurants") {
mutationVariables = {
addMutation: useAddRestaurantMutation()[0],
updateMutation: useUpdateRestaurantMutation()[0],
removeMutation: useRemoveRestaurantMutation()[0],
fetchData: useFetchRestaurantQuery(id),
};
} else if (type === "shows") {
mutationVariables = {
addMutation: useAddShowMutation()[0],
updateMutation: useUpdateShowMutation()[0],
removeMutation: useRemoveShowMutation()[0],
fetchData: useFetchShowQuery(id),
};
}
const {
addMutation,
updateMutation,
removeMutation,
fetchData: { data, isLoading },
} = mutationVariables;
const handleDelete = () => {
removeMutation(id);
navigate(`/${type}`);
}
const handleUpdate = () => {
const updateData = {
id,
name,
park,
area,
completed,
};
updateMutation(updateData);
navigate(`/${type}`);
}
const handleAdd = () => {
const attractionData = {
name,
park,
area,
completed
};
addMutation(attractionData);
navigate(`/${type}`);
}
useEffect(() => {
if (!isLoading && id != null) {
setPark(data.park);
setCompleted(data.completed);
setName(data.name);
setArea(data.area);
}
}, [isLoading]);
return isLoading ? (
<div className="flex items-center justify-center">Loading...</div>
) : (
<div>
<FormGroup className="flex flex-col m-6 gap-4">
<TextField label="Name"
value={name}
onChange={(event) => {
setName(event.target.value);
}}
/>
<Dropdown
options={parks}
value={park}
label="Park"
setValue={setPark}
/>
<Dropdown
options={PARK_AREAS[park]}
value={area}
label="Area"
setValue={setArea}
/>
<FormControlLabel
control={
<Checkbox
checked={completed}
onChange={(event) => {
setCompleted(event.target.checked);
}}
/>
}
label="Completed"
/>
<div className="outline rounded-lg h-80 flex justify-center align-center">
map will go here
</div>
{id != null ? (
<div className="flex justify-center gap-4">
<Button variant="contained" onClick={handleUpdate}>Save</Button>
<Button variant="contained" color="error" onClick={handleDelete}>Delete</Button>
</div>
) : (
<div className="flex justify-center">
<Button variant="contained" onClick={handleAdd}>Create</Button>
</div>
)}
</FormGroup>
</div>
);
}
export default Edit;
Edit.propTypes = {
type: PropTypes.string.isRequired,
};
我尝试移动到自定义挂钩,但遇到了同样的问题。
你不能有条件地调用 React hooks。要解决这个问题,您只需无条件调用所有挂钩即可。将突变触发器和查询结果分配给唯一标识符,并使用
skip
选项有条件地 运行查询。
const [addAttractionTrigger] = useAddAttractionMutation();
const [updateAttractionTrigger] = useUpdateAttractionMutation();
const [removeAttractionTrigger] = useRemoveAttractionMutation();
const fetchAttractionResult = useFetchAttractionQuery(
id,
{ skip: !["restaurants", "shows"].includes(type) } // "attractions"
);
const [addRestaurantTrigger] = useAddRestaurantMutation();
const [updateRestaurantTrigger] = useUpdateRestaurantMutation();
const [removeRestaurantTrigger] = useRemoveRestaurantMutation();
const fetchRestaurantResult = useFetchRestaurantQuery(
id,
{ skip: !["attractions", "shows"].includes(type) } // "restaurants"
);
const [addShowTrigger] = useAddShowMutation();
const [updateShowTrigger] = useUpdateShowMutation();
const [removeShowTrigger] = useRemoveShowMutation();
const fetchShowResult = useFetchShowQuery(
id,
{ skip: !["attractions", "restaurants"].includes(type) } // "shows"
);
let mutationVariables;
if (type === "attractions") {
mutationVariables = {
addMutation: addAttractionTrigger,
updateMutation: updateAttractionTrigger,
removeMutation: removeAttractionTrigger,
fetchData: fetchAttractionResult,
};
} else if (type === "restaurants") {
mutationVariables = {
addMutation: addRestaurantTrigger,
updateMutation: updateRestaurantTrigger,
removeMutation: removeRestaurantTrigger,
fetchData: fetchRestaurantResult,
};
} else if (type === "shows") {
mutationVariables = {
addMutation: addShowTrigger,
updateMutation: updateShowTrigger,
removeMutation: removeShowTrigger,
fetchData: fetchShowResult,
};
}
const {
addMutation,
updateMutation,
removeMutation,
fetchData: { data, isLoading },
} = mutationVariables;