首页 > 解决方案 > React 说我正在对未安装的组件执行状态更新,但我的组件(似乎是)已安装?

问题描述

原谅我,因为我知道我是导致这个错误的人,但我不知道如何 - 我是 React 的新手。

我有一个组件,尽我所能告诉我已安装。该组件从 GitHub 获取流行存储库的列表。该组件有效地允许您过滤按语言返回的存储库列表。该组件使用componentDidMount()生命周期方法来触发对 GitHub API 的请求。在那之后,单击不同的 Nav 元素会触发对 GitHub API 的请求。返回的 repos 列表缓存在 state 中。

值得注意的是,该错误仅在页面加载和刷新时发生。向 3rd 方 API 发送新请求以获取新的 repos 列表不会产生错误。更令我困惑的是,该应用程序显然运行良好 - 在页面加载时,我得到了正确呈现的 repos 列表(显示在某些卡片组件中)。

组件本身是:

export default class Popular extends React.Component {
  state = {
    selectedLanguage: 'All',
    repos: {},
    error: null
  }

  componentDidMount() {
    this.updateLanguage(this.state.selectedLanguage)
  }

  updateLanguage = (selectedLanguage) => {
    this.setState({
      selectedLanguage,
      error: null
    })

    if (!this.state.repos[selectedLanguage]) {
      fetchPopularRepos(selectedLanguage)
        .then(data => {
          this.setState(({ repos }) => ({
            repos: {
              ...repos,
              [selectedLanguage]: data,
            }
          }))
        })
        .catch(() => {
          console.warn('Error fetching repos: ')

          this.setState({
            error: 'There was an error fetching the repositories.'
          })
        })
    }
  }

  isLoading = () => {
    const { selectedLanguage, repos, error } = this.state;

    return !repos[selectedLanguage] && error === null
  }

  render() {
    const { selectedLanguage, repos, error } = this.state

    return (
      <React.Fragment>
        <LanguagesNav
          selected={selectedLanguage}
          onUpdateLanguage={this.updateLanguage}
        />

        {this.isLoading() && <Loading text='Fetching Repos' />}

        {error && <p className='center-text error'>{error}</p>}

        {repos[selectedLanguage] && <ReposGrid repos={repos[selectedLanguage]} />}
      </React.Fragment>
    )
  }
}

在浏览器中,我收到“无法对未安装的组件执行状态更新”,并且 React 开发工具表明错误来自调用setState返回的承诺。fetchPopularRepos

从第三方 API 获取如下图所示:

export function fetchPopularRepos(language) {
  const endpoint = window.encodeURI(`https://api.github.com/search/repositories?q=stars:>1+language:${language}&sort=stars&order=desc&type=Repositories `);

  return fetch(endpoint)
    .then(res => res.json())
    .then(data => {
      if (!data.items) {
        throw new Error(data.message)
      }

      return data.items
    })
}

还有我的 index.js 正在呈现 App 组件:

class App extends React.Component {
  state = {
    theme: 'light',
    toggleTheme: () => {
      this.setState(({ theme }) => ({
        theme: theme === 'light' ? 'dark' : 'light'
      }))
    }
  }

  render() {
    return (
      <Router>
        <ThemeProvider value={this.state}>
          <div className={this.state.theme}>
            <div className='container'>
              <Nav />

              <Switch>
                <Route exact path='/' component={Popular} />
                <Route exact path='/battle' component={Battle} />
                <Route path='/battle/results' component={Results} />
                <Route component={NotFound} />
              </Switch>
            </div>
          </div>
        </ThemeProvider>
      </Router>
    )
  }
}

在此处输入图像描述

编辑:添加了堆栈跟踪的屏幕截图。编辑 2:添加 Router/index.js 文件

标签: javascriptreactjslifecycle

解决方案


我以前做过你做的事情,这是因为ThemeProvider

你在里面设置ThemeProvider的主题Router

尝试在其他组件ThemeProvider之外定义:Router

应用程序.js:

class App extends React.Component {
  state = {
    theme: 'light',
    toggleTheme: () => {
      this.setState(({ theme }) => ({
        theme: theme === 'light' ? 'dark' : 'light'
      }))
    }
  }

  render() {
    return (
        <ThemeProvider value={this.state}>
          <div className={this.state.theme}>
            <Routes />
          </div>
        </ThemeProvider>
    )
  }
}

路线.js:

class Routes extends React.Component {
  render() {
    return (
      <Router>
        <div className="container">
          <Nav />
          <Switch>
            <Route exact path="/" component={Popular} />
            <Route exact path="/battle" component={Battle} />
            <Route path="/battle/results" component={Results} />
            <Route component={NotFound} />
          </Switch>
        </div>
      </Router>
    )
  }
}

推荐阅读