useEffect иногда выдает нулевую ошибку из-за изменений в переменной error из-за приведения - PullRequest
0 голосов
/ 04 февраля 2020

У меня есть страница отправки формы, есть ловушка useEffect, которую я использую для изменения ошибки из Redux, поэтому, когда ошибка возвращается из бэкенда и заполняет редуктор, она обновляет переменную ошибки с помощью 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({

А вот действие после публикации:

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 в подобных ситуациях?

1 Ответ

1 голос
/ 04 февраля 2020

Когда вы сбрасываете ошибки, на редукторе вы устанавливаете error на null, поэтому useSelector возвращает null для переменной error и, таким образом, для ошибки.

Я думаю, вы можете выбрать несколько альтернатив:

  • во время очистки вы можете установить для ошибок {} вместо нуля
  • useEffect может иметь ошибку (а не error.image) в своих зависимостях, поэтому внутри useEffect вы должны проверить, имеет ли ошибка значение null

Кроме того, я считаю, что ошибка sel не нужна, поскольку useSelector перезаписывает ее. И, как пишут adiga, вы должны установить initialFormState без {}. Другое мнение: я думаю, что вы не можете сделать error.image = "" без использования dispatch

...