我是redux和hooks的初学者,我正在处理表单,尝试通过useDispatch
hooks调用一个action,但是它调用了我的action两次。
我指的是this文章。
下面是一个例子:
- 使用配置文件表单. js**
import { useState, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchProfile } from '../../../redux/profile/profile.actions';
const useProfileForm = (callback) => {
const profileData = useSelector(state =>
state.profile.items
);
let data;
if (profileData.profile) {
data = profileData.profile;
}
const [values, setValues] = useState(data);
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchProfile());
}, [dispatch]);
const handleSubmit = (event) => {
if (event) {
event.preventDefault();
}
callback();
};
const handleChange = (event) => {
event.persist();
setValues(values => ({ ...values, [event.target.name]: event.target.value }));
};
return {
handleChange,
handleSubmit,
values,
}
};
export default useProfileForm;
- 行动**
export const FETCH_PROFILE_BEGIN = "FETCH_PROFILE_BEGIN";
export const FETCH_PROFILE_SUCCESS = "FETCH_PROFILE_SUCCESS";
export const FETCH_PROFILE_FAILURE = "FETCH_PROFILE_FAILURE";
export const ADD_PROFILE_DETAILS = "ADD_PROFILE_DETAILS";
function handleErrors(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response;
}
function getProfile() {
return fetch("url")
.then(handleErrors)
.then(res => res.json());
}
export function fetchProfile() {
return dispatch => {
dispatch(fetchProfileBegin());
return getProfile().then(json => {
dispatch(fetchProfileSuccess(json));
return json;
}).catch(error =>
dispatch(fetchProfileFailure(error))
);
};
}
export const fetchProfileBegin = () => ({
type: FETCH_PROFILE_BEGIN
});
export const fetchProfileSuccess = profile => {
return {
type: FETCH_PROFILE_SUCCESS,
payload: { profile }
}
};
export const fetchProfileFailure = error => ({
type: FETCH_PROFILE_FAILURE,
payload: { error }
});
export const addProfileDetails = details => {
return {
type: ADD_PROFILE_DETAILS,
payload: details
}
};
- 减速器:**
import { ADD_PROFILE_DETAILS, FETCH_PROFILE_BEGIN, FETCH_PROFILE_FAILURE, FETCH_PROFILE_SUCCESS } from './profile.actions';
const INITIAL_STATE = {
items: [],
loading: false,
error: null
};
const profileReducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case ADD_PROFILE_DETAILS:
return {
...state,
addProfileDetails: action.payload
}
case FETCH_PROFILE_BEGIN:
return {
...state,
loading: true,
error: null
};
case FETCH_PROFILE_SUCCESS:
return {
...state,
loading: false,
items: action.payload.profile
};
case FETCH_PROFILE_FAILURE:
return {
...state,
loading: false,
error: action.payload.error,
items: []
};
default:
return state;
}
}
export default profileReducer;
**Component:**
import React from 'react';
import { connect } from 'react-redux';
import useProfileForm from './useProfileForm';
import { addProfileDetails } from '../../../redux/profile/profile.actions';
const EducationalDetails = () => {
const { values, handleChange, handleSubmit } = useProfileForm(submitForm);
console.log("values", values);
function submitForm() {
addProfileDetails(values);
}
if (values) {
if (values.error) {
return <div>Error! {values.error.message}</div>;
}
if (values.loading) {
return <div>Loading...</div>;
}
}
return (
<Card>
...some big html
</Card>
)
}
const mapDispatchToProps = dispatch => ({
addProfileDetails: details => dispatch(details)
});
export default connect(null, mapDispatchToProps)(EducationalDetails);
同样,当我将数据从const [values, setValues] = useState(data);
useState传递到值时,理想情况下我应该在组件中接收它,但我没有得到,因为它显示为未定义。
const { values, handleChange, handleSubmit } = useProfileForm(submitForm);
- 未定义值 *
2条答案
按热度按时间dnph8jn41#
动作的两次分派可能是因为您在react层次结构中使用了
React.StrictMode
。根据react文档,为了
detect unexpected sideEffects
,react会两次调用某些函数,例如现在,由于react-redux是在react API之上实现的,因此操作实际上被调用了两次
当我从const [values,setValues] = useState(data)传递数据时;useState的值,那么理想情况下,我应该在组件中接收,但我没有得到,因为它显示为undefined。
要回答这个问题,您必须知道values不是reducer的dispatch操作响应的结果,而是在调用handleChange时更新的状态,因此应该保持不受操作影响
我认为您的意思是公开
useProfileForm
中的redux数据,但忘记了您可以使用组件中的数据,如
hwamh0ep2#
有两种方法可以克服这个问题。我已经研究了这个问题,并找到了一个解决方案,从react中的根文件中删除React.StrictMode,如
喜欢这个
但是React.StrictMode模式非常适合捕捉代码中的警告和问题。所以我找到了另一种方法来解决这个问题,我们必须在useEffect中使用异步调用来避免双重API调用。所以我在useEffect中使用api调用,如下所示
也可以使用promise创建异步调用