bencripps / react-redux-grid

A React Grid/Tree Component written in the Redux Pattern
http://react-redux-grid.herokuapp.com/
MIT License
444 stars 63 forks source link

Grid displays only empty data message #151

Closed ksnyder closed 7 years ago

ksnyder commented 7 years ago

This library looks very powerful, but I've run into problems trying to get a basic example working in my code. I've run the examples successfully, and tried copying the same config for the 'Editable' example into my code, but the grid only displays column headers and the emptyDataMessage.

With the Chrome React dev tools, I see that TableContainers prop rowProps.dataSource is null, so I try to trace where it's getting lost.

Here's where I start (the values of columns, data and events below are all copied from the 'Editable' example):

const simpleData = {
                columns,
                data,
                pageSize: 20,
                plugins: {
                    EDITOR: {
                        enabled: true,
                        type: 'grid'
                    }
                },
                events,
                stateKey: 'bids',
                emptyDataMessage: 'At least the empty data message works'
            }
            console.log("==== Grid attrs = ", simpleData)
            return (
                <Grid { ...simpleData }
                />
            )

I've traced the code up to the point of the setData function in the GridActions file, and right before that function's return statement, I verify that the data array has made it this far by logging it:

==== GridActions.setData, data =  [Object, Object]0: ObjectAddress: "7815 Accumsan St."Email: "dui.nec@Seddictum.co.uk"Name: "Sawyer"Phone Number: "(209) 915-9426"__proto__: Object1: ObjectAddress: "P.O. Box 994, 452 Sed Rd."Email: "vitae.sodales@leoMorbi.com"Name: "Chadwick"Phone Number: "(666) 320-2563"__proto__: Objectlength: 2__proto__: Array(0)

I'm a big bogged down at the moment trying to find the reducer that will handle this action, in order to continue tracing, so I'm hoping others may have some insight.

I've also verified that gridType is set to 'grid' (which happens by default since I am not specifying).

Thanks!

bencripps commented 7 years ago

How are you importing/incorporating the grid reducers?

ksnyder commented 7 years ago

I wasn't aware I needed to take care of that. I just checked the docs again and could only find info in importing custom reducers -- perhaps you could point me to the right doc or example? Thx.

bencripps commented 7 years ago

https://github.com/bencripps/react-redux-grid/blob/master/docs/USING_GRID_REDUCERS.md

ksnyder commented 7 years ago

Thanks. For some reason the destructuring call on the reducers doesn't work, although I use the same syntax elsewhere:

import { Reducers as gridReducers } from 'react-redux-grid'

ERROR in ./src/shared/reducers.es6
Module build failed: SyntaxError: Unexpected token (86:4)

  84 | 
  85 | const reducers = combineReducers({
> 86 |     ...gridReducers });
     |     ^
  87 | 
  88 | export default reducers

I thought I would nest the reducers instead, but that doesn't want to compile on the server, I guess:

import { GridRootReducer } from 'react-redux-grid'

/Users/byofuel/code/tonicmart/node_modules/react-redux-grid/dist/components/layout/header/Column.js:30
var isChrome = /Chrome/.test(navigator.userAgent) && /Google Inc/.test(navigator.vendor);
                             ^

ReferenceError: navigator is not defined
    at Object.<anonymous> (/Users/byofuel/code/tonicmart/node_modules/react-redux-grid/dist/components/layout/header/Column.js:30:30)
bencripps commented 7 years ago

This isn't a isomorphic component (yet) so it won't render on the server currently :(

ksnyder commented 7 years ago

Right, I got around that with the Grid component, but I'm puzzled that importing the reducers makes a call to navigator, so I'm trying to figure out a way around it here. I can live without the Grid being rendered on the server, but I need the rest of the project to build on the server.

bencripps commented 7 years ago

Well, this has to do with how node works. Since you're a requiring a file, that requires the other files, it's causing the issue. You won't be able to require index.js (which exports the reducers) since it also requires the main component.

ksnyder commented 7 years ago

I think the require problem is solved by the fact that I am building the store differently for each environment anyway -- on the server createStore takes only the reducers, on the client it also takes the preloaded state of the app. So now I'm just adding the grid reducers on the client call, but I'm back at the original problem where dataSource is null in the TableRow component.

bencripps commented 7 years ago

Sounds like the reducers aren't being imported properly. If you look at the state node, does it have the grid data in it?

ksnyder commented 7 years ago

Hmmm, not sure what the state node is, do you mean the Redux store?

ksnyder commented 7 years ago

I've included some screenshots of the React tree showing props for the Grid and TableContainer components. Note that I'm using react-redux's connect function, and I wonder if that's playing a role here.

screen shot 2017-04-04 at 6 06 57 pm screen shot 2017-04-04 at 6 08 29 pm
bencripps commented 7 years ago

The props are being loaded correctly however, the store is not getting the reducers correctly. If you expand the store here, you should see all grid reducers as being registered. dataSource and the other grid reducers need to be loaded in order for the data to register when actions are fired. Can you provide a screen shot of your expanded store object?

ksnyder commented 7 years ago

Thanks, currently it's being set up with this code:

import { Reducers as gridReducers } from 'react-redux-grid'
const reducers = combineReducers(reducersObj, ...gridReducers)
const store = createStore(reducers, preloadedState, applyMiddleware(thunk))
render((
    <Provider store={store}>
        <App history={browserHistory}/>
    </Provider>
), document.getElementById('content'));

My own reducers are working. Here are some screenshots that show more of the store:

screen shot 2017-04-05 at 7 38 39 am screen shot 2017-04-05 at 7 39 15 am
bencripps commented 7 years ago

Can you please post a screen shot of store.getState() and possibly store.getState().toJS() if you store state as an immutable object. Showing me the methods off the store isn't super helpful :)

ksnyder commented 7 years ago

OK, I'm a bit in the dark as to how this library is supposed to work. In my component that instantiates Grid, I create this fn which is passed to connect():

function mapStateToProps(store) {
    return { currentUser: store.currentUser, bidRequests: store.bidRequests, bids: store.bids.toJS() }
}

These are the only parts of the store exposed in the Grid component:

$r
Grid {props: Object, context: Object, refs: Object, updater: Object, setGridDataType: function…}
$r.context.store.getState()
Object {currentUser: Object, bidRequests: Object, bids: Map}

For the TableContainer, the React context is empty, and I don't see any part of the store in props.

I had thought the store on Grid might contain a key 'bidGrid' since that is the stateKey I'm using, but I don't see it.

Perhaps part of the problem is that TableContainer is not returned wrapped in a connect() call?

bencripps commented 7 years ago

I'm nearly 100% percent sure the bug here isn't with the component, but with how you're initializing the store. Please compare your version to the demo that comes with the npm package, or to the demo-app which source code is here: https://github.com/bencripps/react-redux-grid-demo

I'm going to close this issue for now, as there are many implementations of grid out there in the wild, so this seems like a bug in the setup rather than the component.

ksnyder commented 7 years ago

OK, I have spent considerable time comparing mine to the demo app. Do you have any docs on how we're supposed to pass the store around for your library? I'm using the standard way of handling store per react-redux with Provider, but in your library some components (like BulkActionToolbar) are wrapped with connect() and have the store in React context, whereas other components (like TableContainer) are not, and have no context -- I'm puzzled why there is that difference.

bencripps commented 7 years ago

store isn't a required prop for Grid. It will inherit it from the context of the application (provided you're passing store to the provider). Don't worry about the internals of grid, and how it accesses store (in some cases it's being pulled from context, and in others it's passed as a prop).

Your problem right now isn't with how Grid is getting the store, but how the reducers are being registered with the store.

import { Reducers as gridReducers } from 'react-redux-grid';
const rootReducer = combineReducers({
   ...gridReducers,
   app: customAppReducer,
});

Take a look at this file for more info https://github.com/bencripps/react-redux-grid-demo/blob/master/src/redux/configureStore.js

Even though your store is being created, (making it possible for the grid to load), when the grid goes to fire actions, since the reducers haven't been registered, there's no place to put the data from the actions.