useState не считывает переменную вне оператора if

#reactjs #if-statement #use-state

Вопрос:

Я пытаюсь установить переменную «список» в операторе «если», а затем обновить свои данные с помощью useState, но если я напишу setData вне оператора «если», это покажет, что переменная «список» не определена, поэтому я должен переписать весь код внутри оператора «если» и «еще» (что нежелательно).

 const [data, setData] = useState({
  name: "",
  email: "",
  machinetype: [],
});

const handleInputChange = (event) => {
  if (event.target.name === "machinetype") {
    const chck = event.target.checked;
    if (chck) {
      const list = data[event.target.name].concat([event.target.value]);
    } else {
      const index = data[event.target.name].indexOf(event.target.value);
      const remove = data[event.target.name].splice(index, 1);
      const list = data[event.target.name];
    }
    setData({
      ...data,
      [event.target.name]: list,
    });
  }
};
 

Какие-нибудь советы? Спасибо

Комментарии:

1. Переменные Const ограничены областью их непосредственного окружения { } фигурными скобками и не могут быть доступны во внешней лексической области. Определите переменную над блоком if с помощью » let » вместо этого

Ответ №1:

переменные, объявленные в операторах if, остаются в пределах области действия оператора if. Поэтому, когда указатель покидает блок if, переменная удаляется.

все, что вам нужно сделать, это следующее

 const [data, setData] = useState({
  name: "",
  email: "",
  machinetype: [],
});

const handleInputChange = (event) => {
  if (event.target.name === "machinetype") {
    const chck = event.target.checked;
    let list = null;
    if (chck) {
      list = data[event.target.name].concat([event.target.value]);
    } else {
      const index = data[event.target.name].indexOf(event.target.value);
      const remove = data[event.target.name].splice(index, 1);
      list = data[event.target.name];
    }
    setData({
      ...data,
      [event.target.name]: list,
    });
  }
};
 

Ответ №2:

Переместите объявление list за пределы ifs.

Вы также захотите убедиться, что вы не изменяете список внутренне, не копируя его, так что в целом что-то вроде

 const [data, setData] = useState({
  name: "",
  email: "",
  machinetype: [],
});

const handleInputChange = (event) => {
  const {name} = event.target;
  if (name !== "machinetype") {  // early return to make the function shallower
    return;
  }
  const list = [...data[name]]; // shallow copy
  if (event.target.checked) {
    list.push(event.target.value);
  } else {
    const index = list.indexOf(event.target.value);
    list.splice(index, 1);
  }
  setData({
    ...data,
    [name]: list,
  });
};
 

должно сработать.

Ответ №3:

В то время как вы можете объявить list об этом заранее с let помощью …

 if (event.target.name === "machinetype"){
  const chck = event.target.checked
  let list;
  // assign to list...
 

Более правильным подходом ИМО было бы объединить эти две возможности в единое выражение.

 if (!chck) {
    // this block doesn't make much sense though
    const index = data[event.target.name].indexOf(event.target.value);
    const remove = data[event.target.name].splice(index, 1);
}
const list = data[event.target.name].concat(chck ? [event.target.value] : []);
setData({
  ...data,
  [event.target.name]: list,
});
 

Но присвоение неиспользуемой переменной remove не имеет смысла, и мутация никогда не должна выполняться для состояния в React. Лучше сделать что-то вроде

 const handleInputChange = ({ target }) => {
    const { name, value, checked } = target;
    if (name !== "machinetype") return;
    if (checked) {
        setData({
            ...data,
            [name]: [...data[name], value],
        });
    } else {
        setData({
            ...data,
            [name]: data[name].filter(existingVal => existingVal !== value)
        });
    }
};
 

Комментарии:

1. Однако этого не хватает .splice() , чтобы удалить все из списка.