使用 Redux、Thunk、Axios 创建多部分表单组件
Posted
技术标签:
【中文标题】使用 Redux、Thunk、Axios 创建多部分表单组件【英文标题】:Creating a multipart form component with Redux, Thunk, Axios 【发布时间】:2021-06-22 19:34:51 【问题描述】:我正在尝试创建我在 React 中创建的多类型表单的最后阶段。我想我即将创建一个 handleSubmit 方法来将我的多部分表单数据发布到我的后端数据库,但是我收到了以下与 CORS 问题有关的错误消息。
我是否要以正确的方式添加到我的 Redux 存储和后端?我是否需要在我的服务“createDiveSpot”方法中添加某种解析器来分隔文本、数字和图像?这些错误消息是否来自我没有请求标头?
渲染页面时的错误消息
Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
控制台错误
// state for the current field value
const [spot, setSpot] = useState(
diveLocation: "",
diveRegionID: "",
diveTypeID: "",
diveSpotDescription: "",
diveSpotPhotos: "",
error: ''
);
// all onChange functions do the exact same thing, so you only need one
// pass to a component like onChange=handleChange('typeID')
const handleChange = (property) => (e) =>
setSpot(
// override the changed property and keep the rest
...spot,
[property]: e.target.value,
);
// get access to dispatch
const dispatch = useDispatch();
// useEffect with an empty dependency array is the same as componentDidMount
useEffect(() =>
dispatch(requireFieldData());
, []);
const handleSubmitDiveSpot = () =>
const diveSpot =
diveLocation: spot.diveLocation || undefined,
diveRegionID: spot.diveRegionID || undefined,
diveSpotTypeID: spot.diveSpotTypeID || undefined,
diveSpotDescription: spot.diveSpotDescription || undefined,
diveSpotPhotos: spot.diveSpotPhotos || undefined
// do some stuff with the form
createDiveSpot(diveSpot).then((data) =>
if (data.error)
setSpot( ...spot, error: data.error)
else
setSpot( ...spot, error: '', open: true)
)
// do we need to save this to the backend? or just to redux?
dispatch(addDiveSpot(spot));
const classes = useStyles;
return (
// <AppBar title="Enter your dive details"></AppBar>
<form className="diveSpotForm" method="POST" encType="multipart/form-data" onSubmit=handleSubmitDiveSpot>
<>
<Grid container spacing=3
direction="row"
justify="center"
alignItems="center">
<Grid item xs=4>
<FormControl className=classes.formControl>
<PopulateDropdown
dataList=diveTypeList
titleProperty="diveType" // option label property
valueProperty="diveTypeID" // option value property
name="diveType"
placeholder="Dive Type"
label="Select Dive Type"
value=spot.diveTypeID
onChange=handleChange("diveTypeID")/>
</FormControl>
</Grid>
<br />
<Grid item xs=4>
<FormControl className=classes.formControl>
<PopulateDropdown
dataList=regionList
titleProperty="diveRegion" // option label property
valueProperty="diveRegionID" // option value property
name="diveRegion"
placeholder="Dive Region"
label="Select Region"
value=spot.diveRegionID
onChange=handleChange("regionID")/>
</FormControl>
</Grid>
<br />
<Grid item xs=4>
<TextField
label="diveLocation"
placeholder="Dive Location"
name="diveLocation"
margin="normal"
value=spot.diveLocation
onChange=handleSubmitDiveSpot("diveLocation")/>
</Grid>
<br />
<Grid item xs=10>
<FormControl fullWidth className=classes.margin>
<TextField
label="Description"
name="diveSpotDescription"
value=spot.diveSpotDescription
onChange=handleSubmitDiveSpot("diveSpotDescription")
multiline
rowsMax=6/>
</FormControl>
</Grid>
<br />
<Grid item xs=12>
<FormControl fullWidth className=classes.margin>
<label for="photos">Photo Upload</label>
<input
type="file"
name="photo"
value=spot.diveSpotPhotos
onChange=handleSubmitDiveSpot("diveSpotPhotos")/>
</FormControl>
</Grid>
<br />
<Grid item xs=3>
<Button variant="primary" type="submit">
Submit</Button>
<br />
</Grid>
</Grid>
</>
</form>
【问题讨论】:
邮件是404 Not Found
-- 你确定/api/divespots/createdivespot
是正确的URL吗?你的后端可以处理它吗?通常它只是像/api/divespots
这样的一条路径,您将使用PUT
或POST
请求类型来表示您正在创建一个项目,而GET
则用于读取数据。 HTTP Request Methods
部分输入有错误的onChange
函数。你有handleSubmitDiveSpot("diveLocation")
,但它应该是handleChange("diveLocation")
。这就是“太多重新渲染”的原因。
【参考方案1】:
我认为问题始于您如何向onChange
提供处理程序。如果您在渲染时调用函数,而不是传递函数的引用,则会出现超出嵌套更新的问题。
也许,尝试将 onChange=handleChange("diveTypeID")
更改为 onChange=(e)=> handleChange(e,"diveTypeID")
或 onChange=handleChange.bid(this,"diveTypeID")
【讨论】:
handleChange
是一个柯里化函数const handleChange = (property) => (e) =>
,所以可以使用onChange=handleChange("diveTypeID")
,因为它会创建一个事件处理程序(我在另一个问题上为他编写了该函数,哈哈)。 handleSubmitDiveSpot
不是 curried 函数,所以你所说的关于handleSubmitDiveSpot
是正确的。【参考方案2】:
您收到该错误是因为您需要更改设置 onChange 道具的方式。
代替:
onChange=handleChange("diveTypeID")
你应该有这个:
onChange=(event, id) => handleChange(event, "diveTypeID"
React onChange Events
React - Forms
【讨论】:
以上是关于使用 Redux、Thunk、Axios 创建多部分表单组件的主要内容,如果未能解决你的问题,请参考以下文章
React + redux + axios + thunk,等待interceptors.response 刷新token
使用 axios 和 redux-thunk 以 redux-form 发布请求
使用 axios 的 redux-thunk 的通用数据加载器