【问题标题】:Seeing "render is not a function" when trying to use Context API尝试使用 Context API 时看到“渲染不是函数”
【发布时间】:2019-06-13 00:10:34
【问题描述】:

我正在尝试学习 Context API,我想要实现的是在我的标题中显示登录用户,以及根据登录状态操作我的菜单选项(存储 ' 是否安全? isAuthenticated' 状态?)

我的上下文类:

import React from 'react';

const Context = React.createContext();

export class Provider extends React.Component {

    state = {
        isAuthenticated: true,
        user: {
            name: "Joe Smith",
            email: "joe.smith@here.com"
        }
    }

    render() {
        return (
            <Context.Provider value={this.state}>
                {this.props.children}
            </Context.Provider>
        )
    }
}

export const Consumer = Context.Consumer;

所以,非常基本。设置一个状态,稍后在一些子组件中,我想显示chaps名称。

我的 App.js 是使用“提供者”,因此我的所有组件都可以访问这些数据:

import React from 'react';
import { HashRouter , Route, Switch } from 'react-router-dom';
import Home from './components/home';
import Header from './components/header';
import Accounts from './components/accounts';
import Reports from './components/reports';
import Login from './components/login';
import {Container} from 'reactstrap';

import { Provider } from './context';

function App() {
  return (
    <div className="App">
      <Provider>
        <HashRouter>
          <Header />
          <Container>
            <Switch>
              <Route exact path="/" component={Home} />
              <Route exact path="/accounts" component={Accounts} />
              <Route exact path="/reports" component={Reports} />
              <Route exact path="/login" component={Login} />
            </Switch>
          </Container>
        </HashRouter>
      </Provider>
    </div>
  );
}

export default App;

所以在这种情况下,“标题”需要访问我的上下文。 我的标题将显示一个菜单(根据我将添加到上下文中的一些信息,它将显示或隐藏选项、登录按钮等)。

在菜单下,我想显示一个小的信息栏。例如,登录用户名。所以,我的头类看起来像这样:

import React from 'react';
import Menu from './menu';
import InfoBar from './infobar';
import { Consumer } from '../context';

class Header extends React.Component {

    render() {
        const menuStyle = {
            paddingBottom: "5px"
        }

        return(
            <Consumer>
                <div style={menuStyle}>
                    {value => {
                        console.log(value);
                        return (
                            <h1>Test</h1>
                        )
                    }}
                    <Menu  />
                    <InfoBar />
                </div>
            </Consumer>
        )
    }
}

export default Header;

但问题现在发生了。当我运行我的代码时,它会编译并运行,但马上就会出现运行时错误:

TypeError:render 不是函数 updateContextConsumer C:/Storage/Scratch/ReactApp/accufinance/node_modules/react-dom/cjs/react-dom.development.js:16082

我阅读了一些关于退货和多个孩子的信息,但我的代码似乎没有这个问题。任何有助于理解问题和问题发生的地方都会很棒。如果我注释掉'header'中的代码,没有错误......但是......也没有屏幕。它似乎正在该地区发生。

【问题讨论】:

    标签: javascript reactjs


    【解决方案1】:

    上下文消费者使用渲染道具,特别是作为子组件的函数,因此它期望其直接子组件是函数(而不是组件)。在您的情况下,您可以在函数内移动 div:

    <Consumer>
      {value => {
        console.log(value);
        return (
          <div style={menuStyle}>
            <h1>Test</h1>
            <Menu />
            <InfoBar />     
          </div>
        )
      }}
    </Consumer>
    

    当您想将组件的内部状态公开给其子级时,渲染道具非常强大,但当您还想将它与不同类型的子级一起使用时。

    图案是这样的:

    class Parent extends Component {
      state = { name: 'Mike' }
    
      handleChange = (e) => this.setState({ name: e.target.value })
    
      render() {
        // Here's the main difference: We expect `children` to be
        // a function, and we pass name in as the argument
        return children(state.name);
      }
    }
    
    const InputChild = props => <input value={props.name} />
    
    const HeaderChild = props => <h1>{props.name}</h1>
    
    const App = () => {
      return (
        <Parent>
          {name => {
            // We could easily swap in `HeaderChild` here (or
            // anything else!), passing `Parent`'s internal
            // state.name to it instead:
            <InputChild name={name} />
          }
        </Parent>
      )
    }
    

    这就是 Context 工作的原因,因为 Consumer 对其子组件中的组件一无所知,但它可以公开其状态(即来自 Provider 的值)。

    React 文档中有一个关于渲染道具的精彩部分:https://reactjs.org/docs/render-props.html

    【讨论】:

    • 啊,解决了。现在需要弄清楚为什么。我看到了你的文字 - 但我的大脑仍然融化了我的耳朵。 :)
    • 很高兴它成功了!我将通过对渲染道具的更多解释来更新我的答案。
    【解决方案2】:

    如果您使用功能组件并使用useContextcreateContext,您可能会忘记在渲染之前添加“提供程序”,如myContext.Provider 在我的情况下,我通常会忘记.Provider,而是只写&lt;myContext&gt;&lt;/myContext&gt;必须这样做...&lt;myContext.Provider&gt;&lt;/myContext.Provider&gt;

    【讨论】:

    • 这个答案很好。因为我使用函数式组件。
    • 这么简单的错误浪费了我一个小时的时间。拯救了我的一天。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    相关资源
    最近更新 更多