我是React Native的新手,正在尝试构建一个简单的应用程序,以便用户可以更改其用户信息。当我尝试将已经存在的数据加载到表单中时,我的问题开始了,有时会出现此错误:undefined不是对象result [0] .first_name,但并非总是如此。
预先感谢
这是我的代码:
//Action
import { FETCH_USER, UPDATE_USER } from './actionTypes';
export const fetchUser = () => {
return async (dispatch, getState) => {
const url = 'https://reqres.in/api/users?page=1';
const response = await fetch(url, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
}
});
if(!response.ok){
const errorResData = await response.json();
console.log('error', response);
let message = "error";
throw new Error(message);
}
const resData = await response.json();
dispatch({ type: FETCH_USER, data: resData.data });
};
};
我的减速器
import { FETCH_USER } from '../actions/actionTypes';
const initialState = {
data: [],
};
export default (state = initialState, action) => {
switch (action.type) {
case FETCH_USER:
return {
data: action.data
};
default:
return state;
}
};
组件
import { useDispatch, useSelector } from 'react-redux';
import Style from '../../constants/Style';
import Input from '../../components/UI/Input/Input';
import Button from '../../components/UI/Button/Button';
import Textarea from '../../components/UI/Textarea/Textarea';
import * as userActions from '../../store/actions/user';
const FORM_INPUT_UPDATE = 'FORM_INPUT_UPDATE';
const FROM_INITIAL_VALUE = 'FROM_INITIAL_VALUE';
const formReducer = (state, action) => {
if (action.type === FORM_INPUT_UPDATE) {
const updatedValues = {
...state.inputValues,
[action.input]: action.value,
};
const updatedValidities = {
...state.inputValidties,
[action.input]: action.isValid,
};
let updatedFormIsValid = true;
for (const key in updatedValidities) {
updatedFormIsValid = updatedFormIsValid && updatedValidities[key];
}
return {
formIsValid: updatedFormIsValid,
inputValidties: updatedValidities,
inputValues: updatedValues,
};
}
if (action.type === FROM_INITIAL_VALUE) {
return {
...state,
inputValues: action.initialValues,
};
}
return state;
};
const ChangeAccount = props => {
const [error, setError] = useState();
const [refresh, setRefresh] = useState(false);
const dispatch = useDispatch();
const result = useSelector(state => {
return state.user.data.filter(state => state.id == 1);
});
const [formState, dispatchFormState] = useReducer(formReducer, {
inputValues: {
firstname: '',
lastname: '',
email: '',
password: '',
passwordAgain: '',
},
inputValidties: {
firstname: false,
lastname: false,
email: false,
password: false,
passwordAgain: false,
},
formIsValid: false,
});
const inputChangeHandler = useCallback(
(inputIdentifier, inputValue, inputValidity) => {
dispatchFormState({
type: FORM_INPUT_UPDATE,
value: inputValue,
isValid: inputValidity,
input: inputIdentifier,
});
},
[dispatchFormState]
);
const loadUser = useCallback(async () => {
setError(null);
try {
await dispatch(userActions.fetchUser()).then(() => {
setRefresh(false);
});
} catch (err) {
setError(err.message);
}
}, [dispatch, setError]);
const saveHandler = useCallback(async() => {
alert(formState.inputValues.firstname);
});
useEffect(() => {
setRefresh(true);
loadUser();
}, []);
useEffect(() => {
console.log('loadedData', result);
我的错误指向下面的代码
dispatchFormState({
type: FROM_INITIAL_VALUE,
initialValues: {
firstname: result[0].first_name,
lastname: result[0].last_name,
email: result[0].email,
},
});
}, [refresh, dispatchFormState]);
if (!refresh) {
return (
<View style={{ flex: 1, backgroundColor: Style.Colors.lightWhite }}>
<View style={styles.header}>
<Textarea Color={'rgb(77,77,77)'} Size={29.5}>
Settings
</Textarea>
</View>
<View style={styles.heading}>
<Textarea Color={'rgb(77,77,77)'} Size={22.1}>
Account
</Textarea>
</View>
<View
style={{
width: wp('100%'),
justifyContent: 'space-between',
alignItems: 'center',
marginTop: 30,
height: hp('40%'),
}}>
<Input
style={Style.lightInputStyle}
id="firstname"
label="Firstname"
labelColor="rgb(157,157,186)"
errorText="Check firstname"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
initialValue={formState.inputValues.firstname}
initiallyValid={false}
required
/>
<Input
style={Style.lightInputStyle}
id="lastname"
label="Lastname"
labelColor="rgb(157,157,186)"
errorText="Check lastname"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
initialValue={formState.inputValues.lastname}
initiallyValid={false}
required
/>
<Input
style={Style.lightInputStyle}
id="email"
label="Email"
labelColor="rgb(157,157,186)"
errorText="Check email"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
initialValue={formState.inputValues.email}
initiallyValid={false}
required
/>
<Input
style={Style.lightInputStyle}
id="password"
label="Password"
labelColor="rgb(157,157,186)"
errorText="Check password"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
required
/>
<Input
style={Style.lightInputStyle}
id="passwordAgain"
label="Password (again)"
labelColor="rgb(157,157,186)"
errorText="Check password (again)"
autoCapitalize="none"
autoCorrect={false}
keyboardType="default"
onInputChange={inputChangeHandler}
required
/>
</View>
<View
style={{
width: wp('100%'),
alignItems: 'center',
marginTop: hp('10%'),
}}>
<Button
BtnStyle={Style.lightPurpleButton}
Color={Style.Colors.lightWhite}
Size={Style.FontSize.btn}
OnPress={saveHandler}>
Save
</Button>
</View>
</View>
);
} else {
return (
<View style={{ flex: 1, backgroundColor: Style.Colors.lightWhite }}>
<Text>Loading</Text>
</View>
);
}
};
const styles = StyleSheet.create({
header: {
marginTop: 20,
marginLeft: '7%',
},
heading: {
marginTop: 30,
marginLeft: '7%',
},
});
export default ChangeAccount;
答案 0 :(得分:1)
在我看来,您不是在检查结果,特别是您在检查是否在触发dispatchFormState时是否填充了result [0],您可能试图在实际加载结果之前填充表单。另外,您应该检查您的refresh变量,以便仅在不刷新数据时执行调度。
尝试一下:
useEffect(() => {
console.log('loadedData', result);
if (!refresh && result[0]) {
dispatchFormState({
type: FROM_INITIAL_VALUE,
initialValues: {
firstname: result[0].first_name,
lastname: result[0].last_name,
email: result[0].email,
},
});
}
}, [refresh, dispatchFormState]);