【问题标题】:React.js Context API: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components)React.js 上下文 API:元素类型无效:需要字符串(对于内置组件)或类/函数(对于复合组件)
【发布时间】:2018-10-28 20:24:54
【问题描述】:

考虑以下场景:

import React, { Component } from 'react';
import LocaleService from '../Services/LocaleService.js';

const defaultStore = {
    loaded: false,
    locales: []
};

const LocalesContext = React.createContext(defaultStore);
class LocalesProvider extends Component
{
    state = defaultStore;

    load() {
        const service = new LocaleService(), that = this;
        service.fetch().then(function (locales) {
            that.setState({ locales: locales, loaded: true });
        });
    }

    data() {
        return this.state;
    }

    componentDidMount() {
        this.load();
    }

    render() {
        return (
            <LocalesContext.Provider value={this.data()}>
                {this.props.children}
            </LocalesContext.Provider>
        );
    }
}

export default LocalesProvider;
import React, { Component } from 'react';
import Sidebar from './Sidebar.js';
import Topbar from './Topbar.js';
import Content from './Content.js';
import LocalesProvider from './Providers/LocalesProvider.js';

class App extends Component
{
    state = {
        ready: true
    }

    render() {
        if (this.state.ready) {
            return (
                <div>
                    <Topbar/>
                    <section className="section">
                        <section className="columns" style={{height: '100vh'}}>
                            <div>
                                <LocalesProvider.Consumer>
                                    { data => 
                                        (
                                            <Sidebar isReady={data.loaded} locales={data.locales}/>
                                        )
                                    }
                                </LocalesProvider.Consumer>
                            </div>
                            <main className="column" style={{overflow: 'auto', position: 'relative'}}>
                                <Content/>
                            </main>
                        </section>
                    </section>
                </div>
            );
        } else {
            return ('Loading...');
        }
    }
}

export default App;
import React, { Component } from 'react';
import LocalesProvider from './Providers/LocalesProvider.js';
import { NavLink, HashRouter } from "react-router-dom";

class Sidebar extends Component
{
  constructor(props) {
    super(props);
  }

  buildLocaleLinks (locales, uri) {
    if (!this.props.isReady) {
      return 'Loading...';
    } 

    if (!locales.length) {
      return null;
    }

    return locales.map(function (locale) {
      return (
        <li key={'navigation.translate.' + locale.props.key}>
          <NavLink replace to={'/' + uri + '/' + locale.props.key}>
            {locale.props.key}
          </NavLink>
        </li>
      );
    })
  }

    render () {
        return (
    <HashRouter>
        <aside className="menu">
          <p className="menu-label">
            Menu
          </p>
            <ul className="menu-list">
            <li>Translate</li>
            <li>
              <ul>
                <LocalesProvider.Consumer>
                  {locales => (
                    this.buildLocaleLinks(locales, 'translate')
                  )}
                </LocalesProvider.Consumer>
              </ul>
            </li>
            <li>Validate</li>
            <li>
              <ul>
                <LocalesProvider.Consumer>
                  {locales => (
                    this.buildLocaleLinks(locales, 'validate')
                  )}
                </LocalesProvider.Consumer>
              </ul>
            </li>
          </ul>
        </aside>
      </HashRouter>
        );
    }
}

export default Sidebar;

元素类型无效:应为字符串(对于内置组件)或类/函数(对于复合组件),但得到:未定义。您可能忘记从定义组件的文件中导出组件,或者您可能混淆了默认导入和命名导入。

【问题讨论】:

    标签: javascript reactjs react-context


    【解决方案1】:

    LocalesProvider 是组件,而不是上下文,因此它没有 Consumer 属性。我还没有测试过,但如果你导出创建的上下文,它可能会起作用:

    export const LocalesContext = React.createContext(defaultStore);
    

    将您的导入更改为

    import LocalesProvider, { LocalesContext } from './Providers/LocalesProvider.js';
    

    并将&lt;LocalesProvider.Consumer&gt; 替换为&lt;LocalesContext.Consumer&gt;

    【讨论】:

    • 修复了错误,但我现在在状态处理方面遇到了问题。 Context API 不会在状态更新时向底层子级触发componentWillChangeProps 吗?
    • 没关系!我使用的是状态而不是道具,这在侧边栏中是错误的,因为消费者将数据作为道具而不是状态传递!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-27
    • 2020-04-14
    • 2019-07-10
    • 2021-12-08
    • 2020-11-06
    • 1970-01-01
    相关资源
    最近更新 更多