Home > Mobile >  useState not reading variable outside of if statement
useState not reading variable outside of if statement

Time:10-11

I'm trying to set a variable "list" in an "if" statement, and after that, update my data via useState, but if I write setData outside the "if" statement, it shows that the variable "list" is not defined, so I must rewrite all the code inside the "if" and the "else" statement (which is not desirable)

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,
    });
  }
};

Any advices? Thanks

CodePudding user response:

Move the declaration of list outside the ifs.

You'll also want to make sure you're not internally modifying the list without copying it, so all in all something like

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,
  });
};

should do the trick.

CodePudding user response:

variables declared within if statements stay within the scope of the if statement. So when the pointer leaves the if block the variable is disposed of.

all you need to do is the following

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,
    });
  }
};

CodePudding user response:

While you can declare list ahead of time with let...

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

A nicer approach IMO would be to consolidate the two possibilities into a single expression.

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,
});

But the assignment to unused variable remove doesn't make sense, and mutation should never be done to state in React. Better to do something like

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)
        });
    }
};
  • Related