1
votes

I am a newcomer to Ruby on Rails but have an issue with ReactJs. I tried to use React-Router-DOM and Redux but got errors. One of the errors occurred with 'export default connect(structureSelector, mapDispatchToProps)(HelloWorld);'. Do you have any idea with this issue?

Error message

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")%>

After changing import with 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)
1
import {connect} from "react-redux/lib/connect/connect" this line seems odd, try using the standard: import { connect } from 'react-redux' i can see this as only possible issue. If this is a test app, upload it on github and share link, would be better if the above does not work. If above works, let me know and i will add this as answer. (not adding answer because i can't test this)Zia Ul Rehman Mughal
@ZiaUlRehmanMughal Thank you for your comment, This is the git address of this project (github.com/iyamus/ruby_react_200211). I referred to this site(github.com/reduxjs/react-redux/issues/1117) for change this "import {connect} from "react-redux/lib/connect/connect"Flames
@Please tell me if you tried my suggestion, also the thread you linked say same as what I am saying: github.com/reduxjs/react-redux/issues/…Zia Ul Rehman Mughal
If my suggestion does not fix it, please add instructions to run/setup in the readme of the repo so i can try on that.Zia Ul Rehman Mughal
@ZiaUlRehmanMughal As your saying I updated, but get the error like the thread. You could see the error in contentFlames

1 Answers

1
votes

As discussed in the comments and I tried it in the provided github repo, import is wrong.

Chnage

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

TO:

import { connect } from 'react-redux'

And it will fix this error, and should be enough of an answer to the question, following is bonus just as courtesy.

Bonus part

Than you will start getting other provider related errors in your code, that's because of the view file, which looks like:

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

2 issues here:

  1. // is not valid comments in erb(ruby), use # to comment, or remove the lines in their entirety. And app runs fine.
  2. If you want to render HelloWorld component without rendering app, than you need to provide specific store in HelloWorld component, that's not the topic here and not something to be explained in SO, it is about basic of using redux/store/provider etc.

So just first the import and follow point 1 above, and your app will render fine, i tested it on your repo.