由于来自 redux 的 "error" 变量发生变化,useEffect 有时会给出 null 错误

useEffect sometimes gives null error, due to the changes in the "error" variable coming from redux

我有一个表单提交页面, 有一个 useEffect 钩子我用于更改来自 Redux 的错误,所以当来自后端的错误 returns 填充 reducer 时,它通过 useSelector 刷新错误变量,所以我可以在DOM 我用 Material UI

const BugForm = props => {
  const { classes } = props;
  let error = { image: "", title: "", description: "" };
  let modalState = useSelector(state => state.bug.modal);
  error = useSelector(state => state.UI.errors);

  const initialFormState = {
    category: "",
    project: "",
    priority: "",
    viewStatus: "",
    resolution: "",
    reproducibility: "",
    title: "",
    description: "",
    image: ""
  };
  const dispatch = useDispatch();
  const [value, setValue] = useState({ initialFormState });
  const [openErrorSnack, setOpenErrorSnack] = useState(false);

  // this is for the useEffect to just fire one time in the load:
  const firstUpdate = useRef(true); 


 useEffect(() => {
    if (firstUpdate .current) {
      firstUpdate .current = false;
      return;
    }
    setOpenErrorSnack(true);
    error.image = "";
  }, [error.image || ""]);

//for updating the form values:
const updateField = e => {  
    setValue({
      ...value,
      [e.target.name]: e.target.value
    });
  };

当我提交表单时出现错误,有时我第一次加载页面时会发生这种情况,有时不会:

TypeError: Cannot read property 'image' of null
BugForm
C:/Users/2C/Desktop/reactjs/ticketApp/client/src/components/bugForm.js:116
  113 |    }
  114 |    setOpenSnack(true);
  115 |    error.image = "";
> 116 |  }, [error.image || ""]);
      | ^  117 | 
  118 |  const updateField = e => {
  119 |    setValue({

这是 post 操作:

export const postBug = newBug => dispatch => {
  console.log(newBug);
  dispatch({ type: LOADING_UI });
  checkTokenExpire();
  let bodyFormData = new FormData();
  Object.keys(newBug).forEach(key => bodyFormData.append(key, newBug[key]));
  axios({
    method: "post",
    url: "http://localhost:5000/api/bugs/",
    data: bodyFormData,
    headers: { "Content-Type": "multipart/form-data" }
  })
    .then(res => {
      dispatch({
        type: POST_BUG,
        payload: res.data
      });
      dispatch(clearErrors());
      dispatch({ type: CHANGE_MODAL });
    })
    .catch(err => {
      dispatch({
        type: SET_ERRORS,
        payload: err.response.data ? err.response.data : err.response
      });
    });
};

和 UI 错误减速器:

const initialState = {
  loading: false,
  errors: {  },
  modal: false
};

export default function(state = initialState, action) {
  switch (action.type) {
    case SET_ERRORS:
      return {
        ...state,
        loading: false,
        errors: action.payload
      };
    case CLEAR_ERRORS:
      return {
        ...state,
        loading: false,
        errors: null
      };
    case CHANGE_MODAL:
      return {
        ...state,
        modal: true
      };
    default:
      return state;
  }
}

我该如何解决这个问题,在这种情况下是否有正确和安全的方法来使用 useEffect?

当您清除错误时,在 reducer 上,您将 error 设置为 null,因此 useSelector return null 到变量 error 等错误。

我想你可以选择一些替代方案:

  • 在清除过程中,您可以将错误设置为 {} 而不是 null
  • useEffect 在其依赖项中可能有错误(而不是 error.image),因此在 useEffect 中你必须检查错误是否为 null

此外我认为用let sel 错误是没用的,因为useSelector 覆盖了它。 和写 adiga 一样,您必须设置不带 {} 的 initialFormState。 另一个想法:我认为不使用 dispatch

就不能 error.image = ""