0

I'm trying to make an editable list in React with an option to delete some entries. Editing works as intended:

 function handleChange(i){

    let newArr = [...entries]; 
    newArr[i].body = event.target.value; 
    setEntries(newArr);

 }

But if I try to implement deleting:

    let newArr = [...entries]; 
    newArr.splice(i, 1); 
    setEntries(newArr);

React throws the following error:

Rendered fewer hooks than expected. This may be caused by an accidental early return statement.

I'm new to React so probably it's something obvious, therefore my apologies for the question. I honestly googled for quite a long time before asking :) Any suggestions would be greatly appreciated!

4
  • 1
    You'll have to show more code, that error generally means you tried having a hook (useState, useCallback, useMemo etc.) set after a return statement Commented Jul 26, 2020 at 15:32
  • The error you received is caused when you do not use hooks at the of your component or nest them in conditional statements. You should add the code where you call the hooks. Commented Jul 26, 2020 at 15:33
  • Oh, many thanks! @ZacharyRaineri @Çağatay Sel I've found out that the bug is caused by animation in JSX: ` style={useSpring({ fontSize: handleFontSize(i, txt.level) }) }> ` It is so because it uses hooks, am I right? How might it be possible to keep animation working? Thanks a lot! Commented Jul 26, 2020 at 16:24
  • Maybe this post might help: stackoverflow.com/questions/48077103/… Commented Jul 26, 2020 at 17:03

2 Answers 2

0

Going off comment:

"I've found out that the bug is caused by animation in JSX: style={useSpring({ fontSize: handleFontSize(i, txt.level) }) }> ` It is so because it uses hooks, am I right? How might it be possible to keep animation working? Thanks a lot!"

You need to move the useSpring hook up outside of the render (you can just put it at the top of the component):

const springStyles = useSpring({ fontSize: handleFontSize(i, txt.level) })

Then use that constant within the component property:

style={springStyles}
Sign up to request clarification or add additional context in comments.

Comments

0

I highly recommend using the award winning Immer package for all state operations including modifying arrays. Here is an example implementation from their docs.

Immer can be used in any context in which immutable data structures need to be used. For example in combination with React state, React or Redux reducers, or configuration management

The useState hook assumes any state that is stored inside it is treated as immutable. Deep updates in the state of React components can be greatly simplified as by using Immer. The following example shows how to use produce in combination with useState

import React, { useCallback } from "react";
import { useImmer } from "use-immer";

const TodoList = () => {
  const [todos, setTodos] = useImmer([
    {
      id: "React",
      title: "Learn React",
      done: true
    },
    {
      id: "Immer",
      title: "Try Immer",
      done: false
    }
  ]);

  const handleToggle = useCallback((id) => {
    setTodos((draft) => {
      const todo = draft.find((todo) => todo.id === id);
      todo.done = !todo.done;
    });
  }, []);

  const handleAdd = useCallback(() => {
    setTodos((draft) => {
      draft.push({
        id: "todo_" + Math.random(),
        title: "A new todo",
        done: false
      });
    });
  }, []);

  // etc

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.