question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[when using hooks] Cannot update a component from inside the function body of a different component.

See original GitHub issue

When storyboard class component search example is converted to functional (hooks) errors/warnings are thrown.

import React, { Component } from "react"
import SortableTree from "react-sortable-tree"
import "react-sortable-tree/style.css"

const data = [
  {
    title: "Windows 10",
    subtitle: "running",
    children: [
      {
        title: "Ubuntu 12",
        subtitle: "halted",
        children: [
          {
            title: "Debian",
            subtitle: "gone"
          }
        ]
      },
      {
        title: "Centos 8",
        subtitle: "hardening"
      },
      {
        title: "Suse",
        subtitle: "license"
      }
    ]
  }
]

const nodeInfo = row => console.log(row)

export default class App extends Component {
  constructor(props) {
    super(props)

    this.state = {
      searchString: "",
      searchFocusIndex: 0,
      searchFoundCount: null,
      treeData: data
    }
  }

  render() {
    const { searchString, searchFocusIndex, searchFoundCount } = this.state

    const customSearchMethod = ({ node, searchQuery }) =>
      searchQuery &&
      ((node.title &&
        node.title.toLowerCase().indexOf(searchQuery.toLowerCase()) > -1) ||
        (node.subtitle &&
          node.subtitle.toLowerCase().indexOf(searchQuery.toLowerCase()) > -1))

    const selectPrevMatch = () =>
      this.setState({
        searchFocusIndex:
          searchFocusIndex !== null
            ? (searchFoundCount + searchFocusIndex - 1) % searchFoundCount
            : searchFoundCount - 1
      })

    const selectNextMatch = () =>
      this.setState({
        searchFocusIndex:
          searchFocusIndex !== null
            ? (searchFocusIndex + 1) % searchFoundCount
            : 0
      })

    return (
      <div>
        <h2>Find the needle!</h2>
        <form
          style={{ display: "inline-block" }}
          onSubmit={event => {
            event.preventDefault()
          }}
        >
          <input
            id="find-box"
            type="text"
            placeholder="Search..."
            style={{ fontSize: "1rem" }}
            value={searchString}
            onChange={event =>
              this.setState({ searchString: event.target.value })
            }
          />
          &nbsp;
          <button
            type="button"
            disabled={!searchFoundCount}
            onClick={selectPrevMatch}
          >
            &lt;
          </button>
          &nbsp;
          <button
            type="submit"
            disabled={!searchFoundCount}
            onClick={selectNextMatch}
          >
            &gt;
          </button>
          &nbsp;
          <span>
            &nbsp;
            {searchFoundCount > 0 ? searchFocusIndex + 1 : 0}
            &nbsp;/&nbsp;
            {searchFoundCount || 0}
          </span>
        </form>

        <div style={{ height: 300 }}>
          <SortableTree
            treeData={this.state.treeData}
            onChange={treeData => this.setState({ treeData })}
            searchMethod={customSearchMethod}
            searchQuery={searchString}
            searchFocusOffset={searchFocusIndex}
            searchFinishCallback={matches =>
              this.setState({
                searchFoundCount: matches.length,
                searchFocusIndex:
                  matches.length > 0 ? searchFocusIndex % matches.length : 0
              })
            }
            generateNodeProps={row => {
              return {
                title: row.node.title,
                subtitle: (
                  <div style={{ lineHeight: "2em" }}>{row.node.subtitle}</div>
                ),
                buttons: [
                  <button
                    type="button"
                    className="btn btn-outline-success"
                    style={{
                      verticalAlign: "middle"
                    }}
                    onClick={() => nodeInfo(row)}
                  >
                    ℹ
                  </button>
                ]
              }
            }}
          />
        </div>
      </div>
    )
  }
}

image

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:3
  • Comments:5

github_iconTop GitHub Comments

1reaction
IDrissAitHafidcommented, Aug 21, 2020

after going through this issue and reading this, I understood that the warning gets triggered if you want to setState a component synchronously from a different component.

So I have found a workaround to make the warning disappear, till it’s fixed.

If you click on the little arrow beside Warning, you’ll get a much detailed stacktrace. For me, I have found the warning is triggered by the callback I pass to searchFinishCallback (because it’s there where I change the state of my component from SortableTree component).

So, I changed my callback from something like this:

const searchFinishCallback = (matches) => {
      setSearchFoundCount(matches.length)
      setSearchFocusIndex((searchFocusIndex) =>
        matches.length > 0 ? searchFocusIndex % matches.length : 0
      )
  } 

To something like this:

const searchFinishCallback = (matches) => {
    setImmediate(() => {
      setSearchFoundCount(matches.length)
      setSearchFocusIndex((searchFocusIndex) =>
        matches.length > 0 ? searchFocusIndex % matches.length : 0
      )
    })
  } 

You can instead use setTimeout or anything that will make the call async.

1reaction
CareyToboocommented, Aug 10, 2020

Any news on this one? I have the same problem~

Read more comments on GitHub >

github_iconTop Results From Across the Web

Cannot update a component from inside the function body of a ...
I noticed a small problem with the solution I posted. When the records of the Redux store are updated asynchronously, the useEffect is...
Read more >
Bug: too hard to fix "Cannot update a component from inside ...
The problem is when one component queues an update in another component, while the first component is rendering. In other words, don't do...
Read more >
How I fixed 'Cannot update a component from inside the ...
In this short article I'll highlight why Cannot update a component from inside the function body of a different component warning happened ...
Read more >
Cannot update a component from inside the function body of a ...
JavaScript : React Warning: Cannot update a component from inside the function body of a different component [ Gift : Animated Search Engine ......
Read more >
How to fix the "cannot update a component while rendering a ...
How to fix the "cannot update a component while rendering a different component" error in React. Published Oct 23 2020. Psssst! The 2023...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found