0

I have table, which is positioned by x value and y value. These values are saved in database. I am using react dnd to positioning these table.

What I am trying to do now is that save all tables position at one click. To do that I made code like below..

constructor() {
 super();
 this.state = {
   tables: []
 }}

saveTables() {
 const { state, dispatch, tables } = this.props;
 this.state.tables.map((table) => {
  const data ={
    id: table.id,
    x: table.x,
    y: table.y,
  }
  dispatch(Actions.save(this.props.tables.channel, data));
 })
}

<button onClick={this.saveTables}>Save</button>

So when component is mounted, i get all information of table into this.state.tables. So with saveTables() function, what I am trying to do is that by mapping this.state.tables dispatch actions to save position of x and y for every single table. However, it triggers error that TypeError: action is undefined

Is it possible to do it like above? or is there any other approaches to save all tables data in one click?

Thanks in advance..

--Edit full error

TypeError: action is undefined[Learn More] app.js:54241:1 routerMiddleware/</</< http://localhost:4000/js/app.js:54241:1 saveTables/< http://localhost:4000/js/app.js:73190:9 map self-hosted saveTables http://localhost:4000/js/app.js:73184:7 bound saveTables self-hosted bound bound saveTables self-hosted ReactErrorUtils.invokeGuardedCallback http://localhost:4000/js/app.js:45316:7 executeDispatch http://localhost:4000/js/app.js:39166:5 executeDispatchesInOrder http://localhost:4000/js/app.js:39189:5 executeDispatchesAndRelease http://localhost:4000/js/app.js:38581:5 executeDispatchesAndReleaseTopLevel http://localhost:4000/js/app.js:38592:10 forEach self-hosted forEachAccumulated http://localhost:4000/js/app.js:50930:5 EventPluginHub.processEventQueue http://localhost:4000/js/app.js:38795:7 runEventQueueInBatch http://localhost:4000/js/app.js:45345:3 ReactEventEmitterMixin.handleTopLevel http://localhost:4000/js/app.js:45356:5 handleTopLevelImpl http://localhost:4000/js/app.js:45438:5 TransactionImpl.perform http://localhost:4000/js/app.js:50185:13 ReactDefaultBatchingStrategy.batchedUpdates http://localhost:4000/js/app.js:45084:14 batchedUpdates http://localhost:4000/js/app.js:48223:10 ReactEventListener.dispatchEvent http://localhost:4000/js/app.js:45513:7 bound

D.R
  • 829
  • 4
  • 16
  • 30
  • You could add the data to an array in the loop and dispatch outside the loop, that would be more efficient. Also you haven't provided enough info on the TypeError, there isn't even a reference to `action` there – Dominic Feb 13 '17 at 08:49
  • I just uploaded full error stack.. would you mind elaborating more about loop? – D.R Feb 13 '17 at 08:58

1 Answers1

2

You can map all the data you need to save and then dispatch an action (this will be more efficient as your app will only run the rendering routine once).

saveTables() {
  const { dispatch, tables } = this.props;
  const tableData = tables.map(table => ({
    id: table.id,
    x: table.x,
    y: table.y,
  });
  dispatch(Actions.save(tables.channel, tableData));
}

tableData should then be an array like:

[{id, x, y}, {id, x, y} ...]

Of course you will have to modify the action/reducer to deal with an array of all the data.

As for the action you need to provide the code where the error happens (not just the stack trace), but it will probably be hard to know without a running example.

Dominic
  • 62,658
  • 20
  • 139
  • 163
  • thanks for reply. So for the action, I need to loop it again to insert all objects to the database. For example, if I have 6 tables, tableData will be [{1, x, y}... {6,x,y}]. To insert all 6 tables, i need to loop it. Am I correct? – D.R Feb 13 '17 at 13:49
  • It depends how you want to access it your app, when this enters your reducer, you would usually just store the array into the state of that reducer without needing to loop. If you need it to render something in the app out, you would loop over it in the react component – Dominic Feb 13 '17 at 13:58