简体   繁体   中英

Error: Rendered more hooks than during the previous render, handleRemove causing rendered more hooks error

fields array contains different field objects, on every field using map function there is a remove button but handleRemove function is causing error "Rendered more hooks than during the previous render."

const [fields, setFields] = useState([
  { name: "abc", value: "" },
  { name: "def", value: "" }
]);

...

{
  {fields.map((field, index) => {
    const [now, setNow] = useState(field.value);
    const [isFocused, setIsFocused] = useState(false);

    const handleRemove = (index) => {
      const newFields = fields;
      newFields.splice(index, 1);
      setFields(newFields);
    };

    return (
      <View key={index}>
        <TextInput
          onFocus={() => setIsFocused(true)}
          onBlur={() => setIsFocused(false)}
          onChangeText={handleChange}
          value={now}
        />
        <TouchableOpacity
          onPress={() => {
            handleRemove(index);
          }}
        >
          <Ionicons name="close" style={[tw``]} size={22} color="#ddd" />
        </TouchableOpacity>
      </View>
    );
  })}
}

The code is breaking the Rules of Hooks : Only call hooks at the top level, don't call hooks inside loops , conditions, or nested functions.

Effectively you should factor out most of the fields.map callback into a React component so the useState hooks are rendered with the JSX and not in the Javascript callback in the loop.

Example:

const Field = ({ field, handleRemove }) => {
  const [now, setNow] = useState(field.value);
  const [isFocused, setIsFocused] = useState(false);

  return (
    <View>
      <TextInput
        style={styles.input}
        onFocus={() => setIsFocused(true)}
        onBlur={() => setIsFocused(false)}
        onChangeText={setNow}
        value={now}
      />
      <TouchableOpacity onPress={handleRemove}>
        <Ionicons name="close" style={[tw``]} size={22} color="#ddd" />
      </TouchableOpacity>
    </View>
  );
};

...

{fields.map((field, index) => {
  const handleRemove = () => {
    setFields((fields) => fields.filter((_, i) => i !== index));
  };

  return (
    <Field key={field.name} field={field} handleRemove={handleRemove} />
  );
})}

编辑 error-rendered-more-hooks-than-during-the-previous-render-handlerremove-causing

Note also the handleRemove logic was updated to avoid a state mutation. Array.prototype.splice mutates the array in-place.

Not ok:

const handleRemove = (index) => {
  const newFields = fields;   // <-- newFields is reference to state
  newFields.splice(index, 1); // <-- .splice mutates state
  setFields(newFields);       // <-- same reference set back into state
};

Ok:

const handleRemove = () => {
   // .filter returns new array reference
  setFields((fields) => fields.filter((_, i) => i !== index));
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM