React - Best way to render rows based on State

React - Best way to render rows based on State

VertaminVertamin Posts: 8Questions: 1Answers: 0
edited January 2021 in Free community support

Im giving it a lot of thought and I've been trying a lot of things for weeks.

Im trying to render my datatables based on a React State so everytime I change, add or remove an element from my array my DataTable updates fully even with rendered React componentes.

Things I have tried and discarded for now:

1.I cannot use ComponentDidUpdate. I can't compare each time my state updates if one value of the array changed, added or removed one element. It may work with few elements but if we start with hunders of elements this will be too slow.

2.I cannot use ColumRender to render my react componentes. Yes it works and I can get a react component rendered, but since it is done ReactDOM.render() it won't update on state changes. It has to be done by linking it to the component parent DOM directly.

3.I cannot use Rows.invalidate(). This works to read UPDATES on the datatables dom. But since I have not inserted it with the datatables API it won't be able to update something that doesn't exist. This brings me back to point one, I can't compare each and everytime I update my state to check if i have to remove a row.

Ideas that are in the air:

If I initialize the html table with all the rows and components loaded into the DOM and after that I initialize my DataTable it works and loads everything into the DatatTables memory.

The thing is if the state gets updated and the DOM changes, datatables won't have it in its memory so it won't register the new elements added to the dom. If I do something like search it will just delete the changes.

This gives me some kind of hope since when you initialize a DataTable it is able to load data from the DOM itself. But once it is initialized it isn't able to get new rows from it.

Does someone have any idea on how to progress trough this?

I've been search a lot trought the internet but no one has something functional that isn't just destroying and recreating the entire DataTable each time the state changes.

I would really apreciate the help, im trying my best.

Answers

  • colincolin Posts: 15,158Questions: 1Answers: 2,587

    The thing is if the state gets updated and the DOM changes, datatables won't have it in its memory so it won't register the new elements added to the dom. If I do something like search it will just delete the changes.

    You could invalidate all the rows in the table with rows().invalidate(), which would cause DataTables to rescan the DOM and get the new values. From what you've described, that may solve your problem.

    Colin

  • VertaminVertamin Posts: 8Questions: 1Answers: 0
    edited January 2021

    Hello Colin, thank you for helping!

    If I remember correctly I tried that as I explained in my point 3.

    The issue was that invalidate works only on rows that already exist on the datatables html body.

    I can't just insert a new row into the html and do rows().invalidate() since it will only trigger on rows that were already existing before. If added a row to the html body with React state rendering, it wont detect it and will just remove it!

    Ill give it a try again, maybe I did something wrong and it doesn't work like that after all.

    I really really apreciate the help. Thank you so much!

  • VertaminVertamin Posts: 8Questions: 1Answers: 0
    edited January 2021

    Yep, it doesn't work for what im trying to do!

    Rows().Invalidate() doesn't work for dynamically added or removed rows on the DOM. (In my case trough React render)

    There was a similar discussion about this on another post. https://datatables.net/forums/discussion/35365/jquery-datatable-invalidate-doesnt-work-for-row-that-have-been-added-dynamically

  • VertaminVertamin Posts: 8Questions: 1Answers: 0
    edited January 2021

    Just created an plain javascript example with the same case.

    1. I initialize the html table with one row
    2. Initialize the DataTables
    3. I updated one row and inserted another into the DOM (With Jquery).
    4. Then I used Rows().Invalidate().
    5. The new row is removed and the one that already did exist is updated.

    I need added and removed rows to be Added/Removed from the DataTables too!

    http://live.datatables.net/jakozeci/1/edit

  • kthorngrenkthorngren Posts: 20,346Questions: 26Answers: 4,776

    Thanks for the simple test case!

    My suggestion is to use row.add(). The docs state this:

    Data to use for the new row. This may be an array, object, Javascript object instance or a tr element. I

    Create the HTML string as a jQuery object which can be used be row.add(). For example:
    http://live.datatables.net/vejibova/1/edit

    Kevin

  • VertaminVertamin Posts: 8Questions: 1Answers: 0

    Im using row.add() as a baseline for everything with DataTables. But that's the problem, I want to be able to use it based on React State, this renders dynamically into the dom based on state.

    To be able to insert each row into the API based on state, everytime the state changes I have to compare each and every one of the values in the array to see if a row has been added, removed or updated to update the DataTable.

    This isn't feasible with a lot of elements. Thats why I wanted to use a state array to render all the rows needed and DataTables just to read all the values from the DOM without having to insert them manually into the API.

  • VertaminVertamin Posts: 8Questions: 1Answers: 0

    To explain myself better:

    I can't make react render a row and then add it with row.add() since it renders directly into the component parent and it isn't able to be stored into a variable or passed to another function.

  • VertaminVertamin Posts: 8Questions: 1Answers: 0
    edited January 2021

    I've made some progress! Im not using DOM manipulation for now though.

    I've created a component called TableRow. In my DataTables component I rended one TableRow component for each of the elements that exist in the state array. Im using the events ComponentDidMount to use Table.Add(row) and ComponentWillUnmount to do this.table.row(index).remove() on the parent table component.

    That way when a new element gets added/removed into the state array the component will add or remove itself from the DataTable without having to check one by one.

    Also I have a update function in CompontentDidUpdate for when the state of that Row changes, for now it removes and adds itself again but Ill try to work out a way to update the existing DataTable cell without having to add it again.

    I tried using row.data update but I can't seem to trigger the Cell.Render event again (If you know how to do this I would be grateful)

    Ill update you!

  • allanallan Posts: 61,787Questions: 1Answers: 10,115 Site admin

    This is really interesting, thanks for writing it up as you go.

    The cell rendering should happen when you call the row().data() method. Here is a little example: http://live.datatables.net/joxoxuxo/1/edit .

    Allan

  • VertaminVertamin Posts: 8Questions: 1Answers: 0
    edited January 2021

    I was using createdCell instead of render. I'll change it and it will probably do the trick!

  • allanallan Posts: 61,787Questions: 1Answers: 10,115 Site admin

    Yes, createdCell will only ever trigger once in the life cycle of a cell. Likewise with createdRow. We don't yet have updated* methods.

    Allan

This discussion has been closed.