0

On my screen I have two columns, the left hand column is a list of transations, the right hand column shows details of the last transaction you clicked on in the list on the left.

The details are populated in response to a redux action ONE_TRANS_LOAD_DETAILS

I generate the list on the left using html, without using React. I want to add an onClick event to dispatch an action with type='ONE_TRANS_LOAD_DETAILS'.

I could do this IF the left hand list was also a rect component, but am having trouble getting access to the store to call the store.dispatch({type:'ONE_TRANS_LOAD_DETAILS', transId: 55});

In my html list on the left, I have <div class='row' onClick="store.dispatch({ type: 'ONE_TRANS_LOAD_DETAILS',transId: {{ $trans->id }} }))"> (I am using laravel with a blade template to generate this html)

I have set the store as an export in my application root code (footer.js):

import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import reducer from './reducer';
import TransDetails from "./components/TransDetails";
export const store = createStore(reducer);
require('./components/Allocations.js');

if (document.getElementById('allocations')) {
    render(
        <Provider store={store}>
            <TransDetails />
        </Provider>,
        document.getElementById('allocations')
    );
}

So how to ensure store is set to the redux store available to the html list on the left?

I have tried:

1) putting the export in the javascript file named 'money.js' that webpack builds for me and I import in the html header thus: <script src="js/money.js"></script> money.js:

require('./bootstrap');
import { store } from './footer.js';

but I get 'store is not defined' when I try and use it in the html list

2) SO I tried a script tag in the body:

</head>
<body>
<script>
import { store } from './footer.js';
</script>
...

but I get 'SyntaxError: Unexpected token {' at the import { store } line

3) I have tried putting the import in the head:

<script>
import { store } from './footer.js';
</script>

But I also get unexpected token error.

4) (Thanks @MTCoatser) I made accessStore be processed by webpack to ensure compatibility: New javascript file storeAccess:

import reducer from './reducer';
import { createStore } from 'redux';
var store = createStore(reducer);

And new line in laravel mix (webpack wrapper) .react('resources/js/storeAccess.js','public/js')

and added <script src="js/storeAccess.js"></script> to head of html

Removed store definition from footer.js:

import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import Allocations from "./components/Allocations";

require('./components/Allocations.js');

if (document.getElementById('allocations')) {
    render(
        <Provider store={store}>
            <Allocations />
        </Provider>,
        document.getElementById('allocations')
    );
}

and as this is loaded after storeAccess.js, the store should be available to that code anyway.

and get store is not defined at onClick="store.dispatch in the html body.

BUT Still get "store is not defined" at the store.dispatch line.

In fact If I console.log(store) in the head, it is also undefined:

...
<script src="js/storeAccess.js"></script>
<script>console.log("In head",store)</script> <-- throws store is not defined
</head>

I hope this is just a javascript scope or formatting question! Help!

NULL pointer
  • 1,116
  • 1
  • 14
  • 27
  • The `import`/`export` syntax [isn’t really supported in browsers yet](https://stackoverflow.com/a/38702635/1813169). You’ll need to use some sort of module bundler to prepare your scripts for use in a browser. My preference is usually [Rollup](https://rollupjs.org/guide/en), but there are plenty of options out there. – MTCoster Feb 13 '19 at 20:51
  • @MTCoaster - I see - I will put the import {store} thorugh web pack and update my question with the result! – NULL pointer Feb 13 '19 at 21:40
  • A) It’s not just that line, you’ve got to pass your *entire* collection of scripts through. B) That’s not how you spell my name ;) – MTCoster Feb 13 '19 at 21:42

1 Answers1

0

I ended up using the global window object. In my html:

<div class='row transactionRow' onClick="window.storeGlobal.dispatch({type:'foo',payload:'bar'});"

and define window.storeGlobal in storeAccess.js:

storeAccess.js:

import { createStore } from 'redux';
window.storeGlobal = createStore(reducer);

storeAccess gets webpacked via laravel mix webpack.mix.js:

webpack.mix.js:

mix.react('resources/js/money.js', 'public/js')
   .react('resources/js/footer.js','public/js')
   .react('resources/js/storeAccess.js','public/js')
   .sass('resources/sass/money.scss', 'public/css');

I messed around for a while trying to export the var store variable with a statement like export store; in the stroeAccess.js but I could not work out how to import it in a way that would work across browsers. The above worked so I ran with it.

NULL pointer
  • 1,116
  • 1
  • 14
  • 27