React-bootstrap-table2: How to pass state into formatter function when updating state via useState?

Created on 5 Apr 2019  路  4Comments  路  Source: react-bootstrap-table/react-bootstrap-table2

I am not sure how to make the actionsFormatter function receive the updated state each time I click on the <TableActions /> component using useState().

What I'd like to happen is to 'show' an options box whenever I click on the <TableActions /> component and I need to pass to it the row id (to know which instance of <TableActions /> is triggered.

See code below:

import React, { useState } from "react";

import BootstrapTable from "react-bootstrap-table-next";

import TableActions from "./TableActions/TableActions.jsx";

function MyComponent() {
    const [selectedRowAction, setSelectedRowAction] = useState(null);

    const handleActionsClick = selectedRowId => {
        setSelectedRowAction(selectedRowId);
    };

    const actionsFormatter = (cell, row) => {
        console.log(selectedRowAction); // this one doesn't update when I trigger "handleAcitionsClick", it just triggers when the component 'mounts', which would be all `null`
        return (
            <TableActions
                isOpen={selectedRowAction === row.id ? true : false}
                onActionClick={handleActionsClick}
                rowId={row.id}
            />
        );
    };

    const data = [
        {
            id: "1",
            name: "Name 1",
            dateAdded: "1 day ago"
        },
        {
            id: "2",
            name: "Name 2",
            dateAdded: "2 days ago"
        },
        {
            id: "3",
            name: "Name 3",
            dateAdded: "3 days ago"
        }
    ];

    const columns = [
        {
            dataField: "id",
            text: "",
            hidden: true
        },
        {
            dataField: "name",
            text: "Name"
        },
        {
            dataField: "dateAdded",
            text: "Date Added"
        },
        {
            dataField: "actions",
            text: "Actions",
            formatter: actionsFormatter
        }
    ];

    const selectRow = {
        mode: "checkbox"
    };

    console.log("here ", selectedRowAction); // this one updates when I trigger "handleActionsClick"
    return (
        <div className="someClass">
            <BootstrapTable
                keyField="id"
                data={data}
                columns={columns}
                classes="someClass2"
                selectRow={selectRow}
            />
        </div>
    );
}

export default MyComponent;

Most helpful comment

@iamacatperson

  1. Don't use state directly in column.formatter, pass the state data though column.formatExtraData
    example and docs

  2. If you will update state data, please make sure you update state in the correctly way(Immutable), you can see this to know how to update state correctly,

tag me if you still have any question, thanks!

All 4 comments

@iamacatperson

  1. Don't use state directly in column.formatter, pass the state data though column.formatExtraData
    example and docs

  2. If you will update state data, please make sure you update state in the correctly way(Immutable), you can see this to know how to update state correctly,

tag me if you still have any question, thanks!

@AllenFang Thank you for your reply. I've tried to now use it in column.formatExtraData as in the example below. However, when I trigger a state change, the formatter doesn't seem to get rerendered along with the rest?

class MyComponent extends Component {
    constructor(props) {
        super(props);
        this.state = { selectedRowAction: null };

        this.handleActionsClick = this.handleActionsClick.bind(this);
    }

    handleActionsClick = selectedRowId => {
        this.setState({ selectedRowAction: selectedRowId });
    };

    render() {
        const data = [
            {
                id: "1",
                name: "Name 1",
                dateAdded: "1 day ago"
            },
            {
                id: "2",
                name: "Name 2",
                dateAdded: "2 days ago"
            },
            {
                id: "3",
                name: "Name 3",
                dateAdded: "3 days ago"
            }
        ];

        const columns = [
            {
                dataField: "id",
                text: "",
                hidden: true
            },
            {
                dataField: "name",
                text: "Name"
            },
            {
                dataField: "dateAdded",
                text: "Date Added"
            },
            {
                dataField: "actions",
                text: "Actions",
                formatExtraData: this.state.selectedRowAction,
                formatter: (cell, row, rowIndex, formatExtraData) => {
                    console.log(formatExtraData); // nothing happens when 
                    return (
                        <TableActions
                            isOpen={formatExtraData === row.id ? true : false}
                            onActionClick={this.handleActionsClick}
                            rowId={row.id}
                        />
                    );
                }
            }
        ];

        const selectRow = {
            mode: "checkbox"
        };

        return (
            <div className="someClass">
                <BootstrapTable
                    keyField="id"
                    data={data}
                    columns={columns}
                    classes="someClass2"
                    selectRow={selectRow}
                />
            </div>
        );
    }
}

@iamacatperson I believe your react-bootstrap-table-next version is too old, please upgrade, thanks!

@AllenFang, using formatExtraData your selected row will re-render, but all the none selected rows receive the same extra data and re-render (unnecessarily)?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

eylonronen picture eylonronen  路  3Comments

Randore picture Randore  路  3Comments

epsyan picture epsyan  路  4Comments

kamarajuPrathi picture kamarajuPrathi  路  4Comments

thevangelist picture thevangelist  路  4Comments