首页 > 解决方案 > React Native TypeError undefined is not an object

问题描述

我是 React Native 的新手,正在尝试构建一个简单的应用程序,用户可以在其中更改其用户信息。当我尝试将已经存在的数据加载到表单中时,我的问题就开始了,有时我会收到此错误:未定义不是对象结果 [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;

标签: reactjsreact-native

解决方案


在我看来,您没有检查结果,特别是您没有检查触发 dispatchFormState 时是否填充了 result[0],您可能试图在实际加载结果之前填充表单。此外,您应该检查您的刷新变量,以便仅在数据未刷新时执行调度。

尝试这个:

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]);

推荐阅读