Introduction
Welcome to another informative blog post on React development! In this article, we’ll explore a common issue encountered when working with React-Bootstrap-Table2. Specifically, we’ll address how to update a cell value in the table and synchronize it with a button component located in a different column. By the end of this post, you’ll have a clear understanding of how to implement this functionality in your React projects. So let’s dive right in!
Problem Description
When using React-Bootstrap-Table2, you may come across a situation where you need to update the value of a cell in the table and ensure that the change is reflected in a button component located in another column. By default, the row object passed to the button component during table creation does not automatically update when a cell value changes. This poses a challenge in maintaining synchronization between the edited cell value and the button component.
Passing Functions and Updating State
To address this issue, we can follow a simple approach. First, we need to create a function that returns the edited value for a specific row and column. This function will be responsible for updating the state of the NominateButton component with the changed value. Let’s name this function getInitialBid
. Here’s an example implementation:
code
getInitialBid = (row) => {
return this.state.data.find(r => r.rank === row.rank).initialBid;
}
In this function, we use the find
method to locate the row with the matching rank in the table’s data, and then retrieve the value from the editable column, which in this case is initialBid
.
Next, we can pass this function down to the button component, NominateButton
, as a prop. Within the buttonFormatter
function, which is responsible for rendering the button, we can assign this function as a property to NominateButton
:
code
const buttonFormatter = (cell, row) => {
return (
<NominateButton
row={row}
auctionId={auctionId}
teamId={teamId}
getInitialBid={this.getInitialBid}
/>
);
}
With this setup, the NominateButton
component will receive the getInitialBid
function as a prop.
The Setup
Let’s start by examining the setup of your react-bootstrap-table2 table. Here’s a snippet of the code:
code
function buttonFormatter(cell, row) {
return (
<NominateButton
row={ row }
auctionId={ auctionId }
teamId={ teamId }
/>
);
}
const queue_columns =
[{
dataField: 'player.num',
text: 'Player Num',
editable: false
}, {
dataField: 'player.name',
text: 'Player',
editable: false
}, {
dataField: 'player.position',
text: 'Position',
editable: false
}, {
dataField: 'initialBid',
text: 'Initial Bid',
}, {
text: 'Nominate',
formatter: buttonFormatter,
editable: false
}]
;
return (
<BootstrapTable
bootstrap4={ true }
keyField='player.num'
data={ this.state.data }
columns={ queue_columns }
cellEdit={ cellEditFactory({ mode: 'click',
blurToSave: true }) }
striped
hover />
);
From the provided code snippet, it seems that the issue arises because the row object is passed into the NominateButton component when the table is initially created. Therefore, when the initialBid column is updated, the updated value is not automatically propagated to the row property of the NominateButton for that row. Consequently, the NominateButton component doesn’t reflect the updated initialBid value in its GraphQL mutation.
The Solution
To address this issue, we can implement a function that retrieves the edited value for a specific row and column, and then pass this function down into the button component. Here’s an updated version of your code:
code
getInitialBid = (row) => {
return this.state.data.find(r => r.rank === row.rank).initialBid;
}
render() {
const { auctionId } = this.props;
const { teamId } = this.props;
const buttonFormatter = (cell, row) => {
return (
<NominateButton
row={ row }
auctionId={ auctionId }
teamId={ teamId }
getInitialBid={ this.getInitialBid }
/>
);
}
// Rest of your code...
}
In the above code snippet, we have added the getInitialBid
function, which retrieves the initialBid value for a specific row based on its rank. This function will be used to update the state of the NominateButton component with the changed value.
Next, we pass this getInitialBid
function as a prop to the NominateButton component. Here’s an example of how the NominateButton component would look:
code
class NominateButton extends Component {
render() {
const { row } = this.props;
const { auctionId } = this.props;
const { teamId } = this.props;
const playerId = parseInt(this.props.row.player.id, 10);
return (
<NominateButtonMutator
auctionId={ auctionId }
teamId={ teamId }
playerId={ playerId }
row={ row }
nominationsOpen={ data.team.nominationsOpen }
subscribeToNominationsOpenChanges={ subscribeToMore }
getInitialBid={ this.props.getInitialBid }
/>
);
}
}
In the NominateButton component, we receive the getInitialBid
function as a prop and pass it along to a NominateButtonMutator component. The NominateButtonMutator component then calls the getInitialBid
function and uses the returned value as a variable in an Apollo mutation.
javascriptCopy code
const NominateButtonMutator = (props) => {
const [submitBid]
= useMutation(SUBMIT_BID_MUTATION);
return (
<div>
<Button
disabled={ !props.nominationsOpen }
onClick={ () => {
let initialBid = props.getInitialBid(props.row);
submitBid({ variables: { auction_id: props.auctionId,
team_id: props.teamId,
player_id: props.playerId,
bid_amount: parseInt(initialBid, 10) } });
}}
variant="outline-success">
Nominate
</Button>
</div>
);
};
In the NominateButtonMutator component, we invoke the getInitialBid
function with the props.row
parameter to obtain the updated initialBid value. We then use this value within the Apollo mutation to perform the necessary actions.
Conclusion
By implementing the above solution, you can now update the state of the NominateButton component with the changed value of the initialBid column. This will allow you to utilize the updated value in your GraphQL mutation.
We hope this article has been helpful in addressing your question. If you have any further inquiries, feel free to ask!