React.js 上下文 API:元素类型无效:应为字符串(对于内置组件)或 class/function(对于复合组件)
React.js Context API: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components)
考虑以下场景:
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;
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
LocalesProvider
是组件,而不是上下文,因此它没有 Consumer
属性。我还没有测试过,但如果你导出创建的上下文,它可能会起作用:
export const LocalesContext = React.createContext(defaultStore);
将您的导入更改为
import LocalesProvider, { LocalesContext } from './Providers/LocalesProvider.js';
并将 <LocalesProvider.Consumer>
替换为 <LocalesContext.Consumer>
。
考虑以下场景:
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;
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
LocalesProvider
是组件,而不是上下文,因此它没有 Consumer
属性。我还没有测试过,但如果你导出创建的上下文,它可能会起作用:
export const LocalesContext = React.createContext(defaultStore);
将您的导入更改为
import LocalesProvider, { LocalesContext } from './Providers/LocalesProvider.js';
并将 <LocalesProvider.Consumer>
替换为 <LocalesContext.Consumer>
。