【问题标题】:Ruby on Rails with React "TypeError: Object(...) is not a function" ErrorRuby on Rails 与 React “TypeError: Object(...) is not a function” 错误
【发布时间】:2020-05-27 16:32:52
【问题描述】:

我是 Ruby on Rails 的新手,但对 ReactJs 有疑问。我尝试使用 React-Router-DOM 和 Redux 但出现错误。 'export default connect(structureSelector, mapDispatchToProps)(HelloWorld);' 发生错误之一。你对这个问题有什么想法吗?

错误信息

TypeError: Object(...) is not a function
    at Module../app/javascript/components/HelloWorld.js (HelloWorld.js:45)
    at __webpack_require__ (bootstrap:19)
    at webpackContext (.*$:11)
    at fromRequireContext.js:13
    at Object.getConstructor (fromRequireContextWithGlobalFallback.js:15)
    at Object.mountComponents (index.js:89)
    at HTMLDocument../node_modules/react_ujs/react_ujs/index.js.ReactRailsUJS.handleMount (index.js:149)
    at Object../node_modules/turbolinks/dist/turbolinks.js.e.dispatch (turbolinks.js:75)
    at r.notifyApplicationAfterPageLoad (turbolinks.js:994)
    at r.pageLoaded (turbolinks.js:948)
ReferenceError: HelloWorld is not defined
    at eval (eval at ./node_modules/react_ujs/react_ujs/src/getConstructor/fromGlobal.js.module.exports (fromGlobal.js:12), <anonymous>:1:1)
    at ./node_modules/react_ujs/react_ujs/src/getConstructor/fromGlobal.js.module.exports (fromGlobal.js:12)
    at Object.getConstructor (fromRequireContextWithGlobalFallback.js:19)
    at Object.mountComponents (index.js:89)
    at HTMLDocument../node_modules/react_ujs/react_ujs/index.js.ReactRailsUJS.handleMount (index.js:149)
    at Object../node_modules/turbolinks/dist/turbolinks.js.e.dispatch (turbolinks.js:75)
    at r.notifyApplicationAfterPageLoad (turbolinks.js:994)
    at r.pageLoaded (turbolinks.js:948)
    at turbolinks.js:872
ncaught Error: Cannot find component: 'HelloWorld'. Make sure your component is available to render.
    at Object.mountComponents (index.js:103)
    at HTMLDocument../node_modules/react_ujs/react_ujs/index.js.ReactRailsUJS.handleMount (index.js:149)
    at Object../node_modules/turbolinks/dist/turbolinks.js.e.dispatch (turbolinks.js:75)
    at r.notifyApplicationAfterPageLoad (turbolinks.js:994)
    at r.pageLoaded (turbolinks.js:948)
    at turbolinks.js:872

package.json*

{
  "name": "rails_react",
  "private": true,
  "dependencies": {
    "@babel/preset-react": "^7.8.3",
    "@rails/actioncable": "^6.0.0",
    "@rails/activestorage": "^6.0.0",
    "@rails/ujs": "^6.0.0",
    "@rails/webpacker": "4.2.2",
    "babel-plugin-transform-react-remove-prop-types": "^0.4.24",
    "babel-polyfill": "^6.26.0",
    "prop-types": "^15.7.2",
    "react": "^16.12.0",
    "react-dom": "^16.12.0",
    "react-redux": "^7.1.3",
    "react-router-dom": "^5.1.2",
    "react_ujs": "^2.6.1",
    "redux": "^4.0.5",
    "reselect": "^4.0.0",
    "turbolinks": "^5.2.0"
  },
  "version": "0.1.0",
  "devDependencies": {
    "webpack-dev-server": "^3.10.3"
  }
}

routers.rb

Rails.application.routes.draw do
  root 'static#index'
  namespace :v1, defaults: { format: 'json'} do
    get 'things' => 'things#index'
  end

  get '*page' => 'static#index', constraints: -> (req) do
    !req.xhr? && req.format.html?
  end
end

configureStore.js

// Redux
import { createStore } from "redux";
import React from "react"

const initialState = {
    things: []
};

function rootReducer(state, action) {
    console.log(action.type);
    switch (action.type) {
        default:
            return state
    }
}

export default class configureStore extends React.Component {
    render() {
        //createStore(reducer, preloadedState)
        const store = createStore(rootReducer, initialState);
        return store;
    }
}

HelloWorld.js

import React, {useState} from "react"
import PropTypes from "prop-types"
import {connect} from "react-redux/lib/connect/connect"
import { createStructuredSelector } from "reselect";

const GET_REQUEST = 'Get request';

function getThings() {
  return {
    type: GET_REQUEST
  };
};

class HelloWorld extends React.Component {
  render() {
    return (
      <React.Fragment>
        Greeting: {this.props.greeting}

        {/* adding button */}
        <button className="getThingsBtn" onClick={() => 
          this.props.getThings()
        }>Get Things</button>
      </React.Fragment>
    );
  }
}
HelloWorld.propTypes = {
  greeting: PropTypes.string
};

const structureSelector = createStructuredSelector({
  things: state => state.things,
});

const mapDispatchToProps = { getThings };
export default connect(structureSelector, mapDispatchToProps)(HelloWorld);

App.js

import React from "react"
import PropTypes from "prop-types"
import HelloWorld from "./HelloWorld";
import { BrowserRouter, Switch, Route } from "react-router-dom";

import { Provider } from "react-redux";
import configureStore from "../configureStore";
const store = configureStore();

class App extends React.Component {
  render() {
    return (
      // Redux installed in your app with Provider
      <Provider store={store}>
        <BrowserRouter>
          <Switch>
            <Route exact path="/" render={() => ("Home")}></Route>
            <Route exact path="/hello" render={() => <HelloWorld greeting="App component" />}></Route>
          </Switch>
        </BrowserRouter>
      </Provider>
    );
  }
}

export default App

index.html.erb

// <%= react_component("HelloWorld", { greeting: "previous index"}) %>
//
<%= react_component("App")%>

使用 import {connect} from "react-redux" 更改导入后;

Uncaught Invariant Violation: Could not find "store" in the context of "Connect(HelloWorld)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(HelloWorld) in connect options.
    at invariant (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:3710:15)
    at ConnectFunction (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:37392:55)
    at renderWithHooks (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:25350:22)
    at updateFunctionComponent (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:27396:24)
    at updateSimpleMemoComponent (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:27336:14)
    at updateMemoComponent (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:27241:18)
    at beginWork$1 (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:29269:20)
    at HTMLUnknownElement.callCallback (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:9369:18)
    at Object.invokeGuardedCallbackDev (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:9418:20)
    at invokeGuardedCallback (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:9471:35)
react-dom.development.js:21838 The above error occurred in the <ConnectFunction> component:
    in ConnectFunction

Consider adding an error boundary to your tree to customize error handling behavior.
Visit /react-error-boundaries to learn more about error boundaries.
logCapturedError @ react-dom.development.js:21838
react-dom.development.js:25204 Uncaught Invariant Violation: Could not find "store" in the context of "Connect(HelloWorld)". Either wrap the root component in a <Provider>, or pass a custom React context provider to <Provider> and the corresponding React context consumer to Connect(HelloWorld) in connect options.
    at invariant (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:3710:15)
    at ConnectFunction (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:37392:55)
    at renderWithHooks (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:25350:22)
    at updateFunctionComponent (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:27396:24)
    at updateSimpleMemoComponent (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:27336:14)
    at updateMemoComponent (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:27241:18)
    at beginWork$1 (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:29269:20)
    at HTMLUnknownElement.callCallback (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:9369:18)
    at Object.invokeGuardedCallbackDev (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:9418:20)
    at invokeGuardedCallback (http://localhost:3000/packs/js/application-bb3c5d4bd7a041206dc3.js:9471:35)

【问题讨论】:

  • import {connect} from "react-redux/lib/connect/connect" 这行似乎很奇怪,请尝试使用标准:import { connect } from 'react-redux' 我认为这是唯一可能的问题。如果这是一个测试应用程序,请将其上传到 github 并分享链接,如果以上不起作用会更好。如果上述方法有效,请告诉我,我会将其添加为答案。 (不添加答案,因为我无法测试)
  • @ZiaUlRehmanMughal 感谢您的评论,这是本项目的 git 地址(github.com/iyamus/ruby_react_200211)。我参考了这个网站(github.com/reduxjs/react-redux/issues/1117)来改变这个“import {connect} from”react-redux/lib/connect/connect”
  • @请告诉我您是否尝试过我的建议,您链接的主题也与我所说的相同:github.com/reduxjs/react-redux/issues/…
  • 如果我的建议没有解决,请在 repo 的自述文件中添加运行/设置说明,以便我可以尝试。
  • @ZiaUlRehmanMughal 正如你所说,我更新了,但得到了像线程一样的错误。您可以在内容中看到错误

标签: javascript ruby-on-rails reactjs redux


【解决方案1】:

正如 cmets 中所讨论的,我在提供的 github 存储库中进行了尝试,导入是错误的。

改变

import {connect} from "react-redux/lib/connect/connect"

到:

import { connect } from 'react-redux'

它会修复这个错误,并且应该足以回答这个问题,以下是礼貌的奖励。

奖金部分

然后你会开始在你的代码中得到其他提供程序相关的错误,这是因为视图文件,它看起来像:

// <%= react_component("HelloWorld", { greeting: "previous index"}) %>
//
<%= react_component("App")%>

这里有 2 个问题:

  1. // 不是 erb(ruby) 中的有效 cmets,请使用 # 进行评论,或将这些行全部删除。应用运行良好。
  2. 如果你想在不渲染应用的情况下渲染HelloWorld组件,那么你需要在HelloWorld组件中提供特定的存储,这不是这里的主题,也不是在SO中解释的东西,它是关于使用redux的基础/store/provider 等。

所以首先导入并按照上面的第 1 点进行操作,您的应用就会呈现正常,我在您的存储库中对其进行了测试。

【讨论】:

  • 我的应用在使用 'react-redux' 中的 'import { connect } 渲染时仍然存在问题。这是关于 'Uncaught Invariant Violation: could not find "store" in the context of "Connect(HelloWorld )”。要么将根组件包装在 中,要么将自定义 React 上下文提供者传递给 ,并将相应的 React 上下文使用者传递给连接选项中的 Connect(HelloWorld)。不过谢谢。
  • 是的,奖金部分是关于这个问题的,这不是因为导入@Fr​​ames,正如我试图解释的那样,它是当你直接渲染 Helloworld 组件时,只需渲染应用程序并从中删除 ...react_component("HelloWorld"... 行您的视图文件,如我的回答中所述。
  • @Frames 此外,在这里,您无法在一篇文章中修复代码中的所有错误,这里的格式是通过问题一次解决一个错误,如果您在自己的搜索中找不到该错误的答案。不变量违例是另一个错误,很常见,是因为误用了redux,你应该可以在网上找到很多资源。