React UI doesn't get updated, why? - reactjs

I have a component, called Bucket, each bucket can have multiple challenges, it looks like this,
The code I have is like this, (much-simplified version)
class CLL_Bucket extends Component {
constructor(props) {
super(props);
this.state = {};
this.state = {
…
bucketChallengesIdx: 0, // to track the index of challegnes
bucketChallenges: this.props.bucket.bucketChallenges || [],
…
};
…
this.onBucketChallengeAdd = this.onBucketChallengeAdd.bind(this);
this.onBucketChallengeIDChanged = this.onBucketChallengeIDChanged.bind(this);
this.onBucketChallengeWeightChanged = this.onBucketChallengeWeightChanged.bind(this);
}
render() {
const bucketIdx = this.props.idx;
return (
<div style={styles.container}>
<div key={bucketIdx} className="row" style={styles.bucketStyle}>
<div className="col-md-2">
…
</div>
<div key={bucketIdx} className="col-md-4">
<div>
<label>
<span className="text-center">Challenges<span>
</label>
<button type="button" className="btn btn-success btn-sm" onClick={() => this.onBucketChallengeAdd()}>Add Challenge</button>
</div>
<table className="table table-bordered table-striped show">
<thead>
<tr>
<th>Challenge ID</th>
<th>Weight</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{this.state.bucketChallenges.map(this.renderBucketChallenges.bind(this))}
</tbody>
</table>
</div>
…
</div>
</div>
);
}
renderBucketChallenges(bucketIdx, idx){
return (
<tr key={idx}>
<td className="col-xs-3 input-group-sm">
<Select
options={challengeIDOptions}
defaultValue={challengeIDOptions[0]}
onChange={this.onBucketChallengeIDChanged.bind(this, idx)}
value={this.state.bucketChallengesID}
isSearchable={true}
/>
</td>
<td className="col-xs-1 input-group-sm">
<input type="text" className="form-control" value={this.state.bucketChallengesWeight}
onChange={(e) => this.onBucketChallengeWeightChanged(idx, e)} disabled={this.props.readOnly}>
</input>
</td>
<td className="col-xs-1 input-group-sm">
…
</td>
<td className="col-xs-1 input-group-sm">
<input className="btn btn-danger btn-sm" id="deleteButton" type="button" value="Delete" onClick={() => this.onDeleteChallenge.bind(this, bucketIdx, idx)} />
</td>
</tr>
);
}
onBucketChallengeAdd(){
var newChallengeIndex = this.state.bucketChallengesIdx + 1;
console.log("onBucketChallengeAdd(): " + newChallengeIndex);
this.setState({bucketChallengesIdx: newChallengeIndex});
this.props.onAddChallenge(this.props.idx, newChallengeIndex);
}
The problem I’m having is, when I click the “Add Challenge” button, I can see from the React developer tool that a new challenge is being added, even though the UI is not updated. When I go to a different tab of my app and come back, the UI is added (a new row for the added challenge is there). Why? Any suggestion on how to fix this? Thanks!
The bigger question is, am I on the right track to make this happen? or i should extract challenge portion to a different component?

Related

Bootstrap modal in React is not opening

I have a table whose items I render through a list. The idea is that, on clicking the name of a row, a modal will open and that will print certain values retrieved from the backend server.
Initially, for the modal, my data-target was the ID of my modal. After looking at this answer I realised that I might be doing something wrong and changed that data-target to the ID of the row. Now the problem is that the modal is not opening at all.
Edit: I realised I was doing something wrong when ID of my modal was fixed because irrespective of whichever name I clicked, the same information was loading. Through console.log I could see that the right values were being passed but only was being displayed.
What am I doing wrong here?
The rendered code for the table is as follows:-
<table className="table">
<thead>
<tr>
<th>S. NO.</th>
<th>NAME</th>
<th>ADDRESS</th>
<th>TELEPHONE</th>
<th>EMAIL</th>
<th>AGE</th>
<th></th>
</tr>
</thead>
<tbody>
{this.state.personData.map((pRow, idx) => (
<>
<PersonModal id={pRow.id} />
<tr key={pRow.id}>
<td>{idx + 1}</td>
<td data-toggle="modal" data-target={pRow.id}>{pRow.name}</td>
<td>{pRow.address}</td>
<td>{pRow.phone}</td>
<td>{pRow.email}</td>
<td>{pRow.age}</td>
<td>
{" "}
<DeleteButton id={pRow.id} onDelete={this.onDelete} />{" "}
</td>
</tr>
</>
</tbody>
</table>
This is the rendered code for the modal:-
render() {
console.log("Component rendered");
return (
<React.Fragment>
<div className="modal" id={this.props.id}>
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-body">
{this.props.id}
</div>
<div className="modal-footer">
<button type="button" className="btn optionsButton" data-dismiss="modal">CLOSE</button>
</div>
</div>
</div>
</div>
</React.Fragment>
);
}

How to access table column values in react

I have create table and inserted values. Now I need to access some of table data and assign into variable for calculation. here I need to calculate total of those column values and assign to label. So may I know the way ??
This is the table I have created.
render(){
return (
<tr>
<td data-th="Product">
<div className="row">
<div className="col-sm">
<h4 className="nomargin">{this.DrugsDetailsRequest.item_name}</h4>
</div>
</div>
</td>
<td data-th="Price"> Rs: {this.DrugsDetailsRequest.totalPrice}</td>
<td data-th="Quantity">
<input name="textInputValue1" type="number" className="form-control text-center" onChange={ this.handleChange } />
</td>
<td data-th="Subtotal" className="text-center"> <input name="textInputValue2" type="number" className="form-control text-center" onChange={ this.handleChange } value={this.DrugsDetailsRequest.totalPrice*this.state.textInputValue1}/></td>
<td className="actions" data-th="">
<button className="btn btn-info btn-sm mr-3" onClick={ this.publish }><i className="fa fa-refresh"></i>Refresh</button>
<button className="btn btn-danger btn-sm" onClick={(e) => this.delete(this.DrugsDetailsRequest._id)}><i className="fa fa-trash-o">Delete</i></button>
</td>
</tr>
);
}
Your question isn’t clear but this is what I understand
A simple solution is. Do this in render before return
const total = this.DrugsDetailsRequest.totalPrice + this.DrugsDetailsRequest.totalPrice*this.state.textInputValue1
console.log(total);// this will get you the total

React table misaligns table header columns with table row columns

I'm trying to figure out why my header and body rows aren't in sync. I'm using semantic ui for the css. Is it because my body rows are rendered in a different component? I tried moving them all to 1 and it didn't make any difference.
<table className="ui celled table" border="1">
<thead>
<tr>
<th >Status</th>
<th >Service Date of Visit</th>
<th >Claim ID</th>
<th >Insurance Plan</th>
</tr>
</thead>
<tbody>
{this.state.claims.map ( claim => <ClaimRow claim= { claim } /> ) }
</tbody>
and inside the component.
const ClaimRow = ( {claim} =this.props ) => (
<Form.Field>
<tr >
<td >
<input type="radio" name={claim._id} label="That Was Me" value="valid" checked={claim.status === 'valid'} />
Valid? <br />
<input type="radio" name={claim._id} label="Looks Like Fraud" value="fraud" checked={claim.status === 'fraud'} />
Fraud? <br />
<input type="radio" name={claim._id} label="Looks Like Fraud" value="notselected" checked={!claim.status && "defaultchecked"} />
Not Yet Sure
</td>
<td > {claim.claimDate} {claim.status}</td>
<td > {claim.claimID} </td>
<td > {claim.carrier} </td>
</tr>
</Form.Field>
);
ClaimRow.propTypes = {
claim: PropTypes.string.isRequired
};
export default
and the table footer
<tfoot className="full-width">
<tr>
<th colspan="4">
<div className="ui small button">
Approve
</div>
<div className="ui small button">
Approve All
</div>
<div className="ui right floated button" >
Next
<i class="right arrow icon"> </i>
</div>
<div className="ui right floated button" >
<i class="left arrow icon"></i>
Prev
</div>
</th>
</tr>
</tfoot>
</table>
Rows should be returning a <tr> at the top level, not a <Form.Field>.
for me adding this class worked.
.ReactTable .rt-tbody .rt-td{
margin-left: 0;
}

React - How to check/uncheck checkboxes in a loop whose values come from redux store

I am trying to build a Notification settings via React and Redux where my against each email address I have few checkboxes say something in the below format.
import React from 'react'
export class NotificationSettings extends React.Component {
constructor(props) {
super(props);
this.getEmailUserRows = this.getEmailUserRows.bind(this)
}
getEmailUserRows() {
let _this = this
let emailRows = this.props.emailRows
let emailTemplate = emailRows.map((row) => {
return (
<tr key={row.email}>
<td height="70">
<span class="txt-limit">
<small>{row.email}</small>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={row.email+"sttng1"}
name={row.email+"sttng1"}
type="checkbox"/>
<label for="sttng1"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={row.email+"sttng2"}
name={row.email+"sttng2"}
type="checkbox"/>
<label for="sttng2"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={row.email+"sttng3"}
name={row.email+"sttng3"}
type="checkbox"/>
<label for="sttng3"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={row.email+"sttng4"}
name={row.email+"sttng4"}
type="checkbox"/>
<label for="sttng4"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={row.email+"sttng5"}
name={row.email+"sttng5"}
type="checkbox"
/>
<label for="sttng5"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="icon-delete"></span>
</td>
</tr>
)
})
return emailTemplate
}
render() {
return (
<div class="accordian-container open">
<div class="webhook-dtl">
<h4>Notification Settings</h4>
<table
width="100%"
border="0"
cellSpacing="0"
cellPadding="0"
class="transaction-detail">
<tbody>
<tr class="tbl-hdng">
<td width="24%" height="52" align="left">Email ID</td>
<td width="19%" class="no-spc">Transactional<br/>Emails</td>
<td width="13%" class="no-spc">Settlement<br/>Emails</td>
<td width="12%" class="no-spc">CRM<br/>Emails</td>
<td width="12%" class="no-spc">Onboarding<br/>Emails</td>
<td width="10%" class="no-spc">Other<br/>Emails</td>
<td width="10%" class="no-spc">Action</td>
</tr>
{this.getEmailUserRows()}
</tbody>
</table><br/>
<br/>
<button class="cmn-btn right">ADD MORE</button>
</div>
</div>
)
}
}
export default NotificationSettings
My JSON that is stored in the redux store:
{
"status": 0,
"rows": 0,
"message": "Merchant Details returned successfully",
"result": [
{
"email": "dashboard2#yopmail.com",
"emailCategoryList": {
"crmEmails": true,
"settlementEmails": true,
"transactionalEmails": true,
"onboardingEmails": true,
"otherEmails": true
},
"isMerchantBusinessEmail": true
},
{
"email": "vinikaty#gmail.com",
"emailCategoryList": {
"crmEmails": true,
"settlementEmails": false,
"transactionalEmails": false,
"onboardingEmails": true,
"otherEmails": true
},
"isMerchantBusinessEmail": false
}
],
"errorCode": null,
"guid": null
}
Pleae help me check/uncheck checkboxes in React not able to figure out what would be the best approach.
EDIT:
Made changes as suggested:
`import React from 'react';
let NotificationSettingRow = (props) => {
let { emailRowData } = props
const toggleCheckbox = () => {
console.log("Yay")
}
return (
<tr key={emailRowData.email}>
<td height="70">
<span class="txt-limit">
<small>{emailRowData.email}</small>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={emailRowData.email+"sttng1"}
name={emailRowData.email+"sttng1"}
{...(emailRowData.emailCategoryList.transactionalEmails ? {checked: true} : {}) }
onChange={toggleCheckbox}
type="checkbox"/>
<label for="sttng1"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={emailRowData.email+"sttng2"}
name={emailRowData.email+"sttng2"}
type="checkbox"/>
<label for="sttng2"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={emailRowData.email+"sttng3"}
name={emailRowData.email+"sttng3"}
type="checkbox"/>
<label for="sttng3"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={emailRowData.email+"sttng4"}
name={emailRowData.email+"sttng4"}
type="checkbox"/>
<label for="sttng4"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="pure-checkbox tog-check">
<input
id={emailRowData.email+"sttng5"}
name={emailRowData.email+"sttng5"}
type="checkbox"
/>
<label for="sttng5"></label>
</span>
</td>
<td class="no-spc" height="70">
<span class="icon-delete"></span>
</td>
</tr>
)
}
export default NotificationSettingRow`
However i am unable to check/uncheck checkboxes. Please help
Look at he last line in input, it basically evaluates if email in current row is in particular category, and if yes it renders checked=true, otherwise renders nothing
<input
id={row.email+"sttng1"}
name={row.email+"sttng1"}
type="checkbox"
{...(row.emailCategoryList.crmEmails ? {checked: true} : {}) }
/>
While you are at it you could define your component that would be used like:
<MyMailCheck row={row} idPrefix="sttng1" rowKey="crmEmails"/>
to avoid typing pretty much the same code for each email category.
Now how to handle checking and unchecking by the user. You need action that will be fired by the onClick for each checkbox. Something along these lines:
const emailCategoryClick = (email, category) => ({
type: 'EMAIL_CATEGORY_CLICK',
email,
category
})
And you need suitable reducer to recognize this action, and update state accordingly.
Lastly, you need to wire your checkboxes to dispatch correct emailCategoryClick actions. To do so, you should connect your component to get access to dispatch method from store. Something like:
export default connect(
(state) => ({}),
(dispatch) => ({catClick: (email, cat) => () => {dispatch(emailCategoryClick(email, cat))} })
)(NotificationSettings)
and in your checkbox you would add onClick handler as in:
<input
id={row.email+"sttng1"}
name={row.email+"sttng1"}
type="checkbox"
{...(row.emailCategoryList.crmEmails ? {checked: true} : {}) }
onCLick={catClick(row.email, "crmEmails")}
/>

How can I make my React app render Bootstrap tables with crud

I'm using the following code to generate a simple UI, and I'm trying to convert it to use Bootstrap.
This is my original code (using Skeleton);
render:function(){
return (
<div className="grocery-item row">
<div className="six columns">
<h4 className={this.props.item.purchased ? "strikethrough" : "" }>
{this.props.item.name}
</h4>
</div>
<form onSubmit={this.togglePurchased} className="three columns">
<button className={this.props.item.purchased ? "btn btn-danger" : "button-primary"}>{this.props.item.purchased ? "unbuy" : "buy"}</button>
</form>
<form className="three columns" onSubmit={this.delete}>
<button>×</button>
</form>
</div>
)
}
I tried doing something like this;
render:function(){
return (
<table class="table table-striped">
<thead>
<tr>
<th>Column 1</th>
<th>Columan 2</th>
<th>Columan 3</th>
</tr>
</thead>
<tbody>
<tr>
<h4 className={this.props.item.purchased ? "strikethrough" : "" }>{this.props.item.name}</h4>
<form onSubmit={this.togglePurchased} className="three columns">
<button className={this.props.item.purchased ? "btn btn-danger" : "button-primary"}>{this.props.item.purchased ? "unbuy" : "buy"}</button>
</form>
<form className="three columns" onSubmit={this.delete}>
<button>×</button>
</form>
</tr>
</tbody>
</table>
)
}
But it's not working like I expect. I'm using react-express-examplar as my starting point.
How can I get Bootstrap tables working in my React app?
I think you'll have an easier time if you start your app using create-react-app. They even give instructions on how to use Bootstrap with React.
You said you're new to React. There are a lot of moving parts that can be overwhelming to figure out at first. Using create-react-app will take out a lot of the learning curve and make it a lot easier for you to get started with as little friction as possible.
Good luck!
From my understanding, you want the name and buy/unbuy buttons to come as a row , under respective columns.
In the tr tag, give each html part as a td tag
Please refer below html snippet:
<td>
<h4 class="strikethrough">
name
</h4>
</td>
<td>
<form class="three columns">
<button class="btn btn-info">buy</button>
</form>
</td>
<td>
<form class="three columns">
<button>×</button>
</form>
</td>
Please try to modify the html in your component render method, similarly.
You added table to wrong Component. It must be on GroceryItemList.jsx
Caution: Form is not allowed inside table. I'm just providing the structure and UI and code is not tested.
::: structure should something like-
GroceryItemList.jsx Component::::
render:function(){
return (
<div>
<table className="table">
<thead>
<tr>
<th>Column 1</th>
<th>Columan 2</th>
<th>Columan 3</th>
</tr>
</thead>
<tbody>
{this.props.items.map((item,index)=>{
return (
<GroceryItem item={item} key={"item"+index} />
)
})}
<GroceryListAddItem />
</tbody>
</table>
</div>
)
}
GroceryItem.jsx Component::::
render:function(){
return (
<tr>
<td>
<h4 className={this.props.item.purchased ? "strikethrough" : "" }>
{this.props.item.name}
</h4>
</td>
<td>
<form onSubmit={this.togglePurchased}>
<button className={this.props.item.purchased ? "" : "button-primary"}>{this.props.item.purchased ? "unbuy" : "buy"}</button>
</form>
</td>
<td>
<form onSubmit={this.delete}>
<button>×</button>
</form>
</td>
</tr>
)
}

Resources