React Bootstrap remote row insert - reactjs

I am attempting insert a row into a table once it has been successfully stored in the database.
I am getting the following error:
Warning: Each child in a list should have a unique "key" prop.
I have added the "rowKey="id" parameter to the table component but I am still facing the same issue.
import React, { Component} from "react";
import editImage from '../../src/images/edit.png';
import './Payrolls.css';
import {BootstrapTable,TableHeaderColumn, RemoteInsertRow} from 'react-bootstrap-table';
import '../../node_modules/react-bootstrap-table/css/react-bootstrap-table.css'
import { Link } from 'react-router-dom'
import axios from "axios";
var currentComponent = null;
class Payrolls extends Component {
componentDidMount() {
this.getData();
}
constructor(props, context) {
super(props, context);
this.tableData = [Array]
this.state = {
tableData: [],
selected: []
};
this.getData = this.getData.bind(this);
this.onAddRow = this.onAddRow.bind(this);
}
getData = () => {
var self=this;
axios.get('http://******.co.uk/payrolls.php', {
})
.then(function (response) {
self.state.tableData.push(response.data)
self.setState({tableData: response.data});
})
.catch(function (error) {
self.props.history.push('/login');
console.log(error);
});
}
dateValidator(value, row) {
if(value === ""){
return 'You must select a date!';
}else{
return true;
}
}
onAddRow = (row) => {
// Save to server and on success:
this.state.tableData.push(row)
this.setState({
tableData: this.tableData
});
}
render() {
const { tableData } = this.state;
const selectRowProp = {
mode: 'checkbox'
};
function editButton(cell, row){
if(row.status !== "Complete") {
return (<img alt="logo" className="imageIcon" src={editImage}/>);
}
}
return (
<div className="grid-item-dashboard-title">
Active Payrolls
</div>
<div className="payroll-table">
<BootstrapTable data={ this.state.tableData } remote={ true } insertRow={ true } pagination={ true } deleteRow={ true } selectRow={ selectRowProp } options={ { onAddRow: this.onAddRow } } striped hover rowKey="id">
<TableHeaderColumn dataField='id' autoValue ={true} isKey={ true } hidden hiddenOnInsert>Payroll ID</TableHeaderColumn>
<TableHeaderColumn dataAlign="center" dataField='creation_date' hiddenOnInsert>Creation Date</TableHeaderColumn>
<TableHeaderColumn dataAlign="center" dataField='created_by' hiddenOnInsert>Created By</TableHeaderColumn>
<TableHeaderColumn dataAlign="center" dataField='week_ending' editable={ { type: 'date' ,validator: this.dateValidator} } >Week Ending</TableHeaderColumn>
<TableHeaderColumn dataAlign="center" dataField='status' hiddenOnInsert>Status</TableHeaderColumn>
<TableHeaderColumn dataAlign="center" dataFormat={editButton}></TableHeaderColumn>
</BootstrapTable>
</div>
</div>
);
}
}
export default Payrolls;

Related

this.state.account and this.state.followers are not updated onMouseOver?

When Bootstrap table rows are hovered the twitter_account in Twitter state is updated.But when passed as props for TwitterChart class It is not updated.
const twitterData = [
{
account: "marwilliamson",
followers: 2610335,
},
{
account: "BernieSanders",
followers: 9254423,
},
{
account: "Hickenlooper",
followers: 144816,
}
]
export {twitterData};
/////////
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
import {twitterData} from './twitter_data'
export const Twitter = () => {
const data = useMemo(() => twitterData, [])
const [twitter_account,settwitter_account] = useState('');
const [twitter_followers,settwitter_followers] = useState(0);
function onRowMouseOver(row){
settwitter_account(row.account);
settwitter_followers(row.followers);
}
const options = {
onRowMouseOver: onRowMouseOver,
};
return (
<div>
<div className="twitter-followers">
<div className="followers-header">
<BootstrapTable data={ data } options={options}>
<TableHeaderColumn dataField='account' dataFormat={CellFormatter} isKey={true} dataSort={ true } dataAlign='left' width='120' headerAlign='left' className="header">ACCOUNT</TableHeaderColumn>
<TableHeaderColumn dataField='followers' dataSort={ true } width='120' dataAlign='center' headerAlign='left' className="header">FOLLOWERS</TableHeaderColumn>
</BootstrapTable>
</div>
</div>
<TwitterBarChart account={twitter_account} followers={twitter_followers}/>
</div>
)
}
/////////
class TwitterBarChart extends React.Component {
constructor(props){
super(props);
this.state = {
data : twitterData,
account:props.account,
followers:props.followers,
}
}
render() {
console.log(this.state.account);
return(
<div className="barchart-msg-container">
<p className="barchart-message"><strong>{this.state.account}</strong> has <span>{this.state.followers}</span> followers on Twitter</p>
</div>
)
}
twitter_account , twitter_followers are not getting updated on props.
console.log(this.state.account) //account value is not updating onMouseOver.
Finally after many references I got the answer.
should use componentWillRecieveProps(newprops){}
Thanks for contributing

how add react-loading in react bootstrap table

i'm new in reactjs and react bootstrap table. i want add react-loading in my react component before data show. because data show so long. but doesn't work.
this is my code
import React, { Component } from 'react';
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
import PageHeader from 'react-bootstrap/lib/PageHeader';
import database from './database';
import root from 'window-or-global';
import Loading from 'react-loading';
class User extends Component {
constructor(props) {
super(props);
this.state = {
text:'',
products: []
};
this.userRef = database.ref('users');
}
componentDidMount() {
this.userRef.on('value', this.gotData, this.errData);
}
gotData = (data) => {
let newProducts = []
const userdata = data.val();
const keys = Object.keys(userdata);
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
newProducts.push({
name: userdata[k].nama, address: userdata[k].address, email: userdata[k].email
});
}
this.setState({products : newProducts});
}
errData = (err) => {
console.log(err);
}
handleClick = (rowKey) => {
alert(this.refs.table.getPageByRowKey(rowKey));
}
render() {
return (
<div>
<Loading type ='spinning-bubbles' color='#e3e3e3' />
<div className="col-lg-12">
<PageHeader>Members</PageHeader>
</div>
<BootstrapTable
ref='table'
data={ this.state.products }
pagination={ true }
search={ true }>
<TableHeaderColumn dataField='name' isKey={true} dataSort={true}>Name</TableHeaderColumn>
<TableHeaderColumn dataField='address' dataSort={true}>Address</TableHeaderColumn>
<TableHeaderColumn dataField='email'>Email</TableHeaderColumn>
</BootstrapTable>
</div>
);
}
}
export default User;
Best wishes! Wish for replying.
For that, first maintain a bool in state variable that will track whether data fetched or not, initial value of that bool will be false.
constructor(){
super();
this.state = {
isDataFetched: false,
}
}
Now there a property of React-Bootstrap-Table, option that is used to set the default values and customise the noDataText, you can use that, like this:
<BootstrapTable
....
options={tableOtions}>
</BootstrapTable>
Now define this tableOtions object and edit the noDataText property, like this:
let tableOtions = {
noDataText: this._setTableOption(),
};
If data is fetched successfully then return some text, that will be displayed if data will be empty, otherwise return a loader:
_setTableOption(){
if(this.state.isDataFetched){
return "No expenses found";
}else{
return(
<RefreshIndicator size={40} left={0} top={0} status="loading" style={{position: 'relative', margin: '0px auto'}}/>
);
}
}
Note: I used a Material-UI RefreshIndicator, you can replace that by any other loader also.
Reference of option object in React Bootstrap Table: http://allenfang.github.io/react-bootstrap-table/docs.html#noDataText
Update: Use this code, and replace the RefreshIndicator by Loader that you want to show:
import React, { Component } from 'react';
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
import PageHeader from 'react-bootstrap/lib/PageHeader';
import database from './database';
import root from 'window-or-global';
import Loading from 'react-loading';
class User extends Component {
constructor(props) {
super(props);
this.state = {
text:'',
products: [],
isDataFetched: false,
};
this.userRef = database.ref('users');
}
componentDidMount() {
this.userRef.on('value', this.gotData, this.errData);
}
gotData = (data) => {
let newProducts = []
const userdata = data.val();
const keys = Object.keys(userdata);
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
newProducts.push({
name: userdata[k].nama, address: userdata[k].address, email: userdata[k].email
});
}
this.setState({products : newProducts, isDataFetched: true});
}
errData = (err) => {
console.log(err);
}
handleClick = (rowKey) => {
alert(this.refs.table.getPageByRowKey(rowKey));
}
_setTableOption(){
if(this.state.isDataFetched){
return "No expenses found";
}else{
return(
<RefreshIndicator size={40} left={0} top={0} status="loading" style={{position: 'relative', margin: '0px auto'}}/>
);
}
}
render() {
let tableOtions = {
noDataText: this._setTableOption(),
};
return (
<div>
<Loading type ='spinning-bubbles' color='#e3e3e3' />
<div className="col-lg-12">
<PageHeader>Members</PageHeader>
</div>
<BootstrapTable
ref='table'
data={ this.state.products }
pagination={ true }
search={ true }
options={tableOtions}>
>
<TableHeaderColumn dataField='name' isKey={true} dataSort={true}>Name</TableHeaderColumn>
<TableHeaderColumn dataField='address' dataSort={true}>Address</TableHeaderColumn>
<TableHeaderColumn dataField='email'>Email</TableHeaderColumn>
</BootstrapTable>
</div>
);
}
}
export default User;

error display data from firebase to react bootstrap table

I want to display data from my firebase database to react bootstrap table. But, I can't show live data if after refresh.
This is my react component code
import React, { Component } from 'react';
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
import PageHeader from 'react-bootstrap/lib/PageHeader';
import database from './database';
const ref = database.ref('users');
ref.on('value', gotData, errData);
const products = [];
function gotData(data) {
const userdata = data.val();
const keys = Object.keys(userdata);
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
products.push({
name: userdata[k].nama, address: userdata[k].address, email: userdata[k].email
});
}
}
function errData(err) {
console.log(err);
}
class Member extends Component {
constructor(props) {
super(props);
this.state = {
text:''
};
}
handleClick = (rowKey) => {
alert(this.refs.table.getPageByRowKey(rowKey));
}
render(){
return (
<div>
<div className="col-lg-12">
<PageHeader>Members</PageHeader>
</div>
<BootstrapTable
ref='table'
data={ products }
pagination={ true }
search={ true }>
<TableHeaderColumn dataField='name' isKey={true} dataSort={true}>Name</TableHeaderColumn>
<TableHeaderColumn dataField='address' dataSort={true}>Address</TableHeaderColumn>
<TableHeaderColumn dataField='email'>Email</TableHeaderColumn>
</BootstrapTable>
</div>
);
}
}
export default Member;
and this is my initialize database code
import firebase from 'firebase';
const config = {
apiKey: '......',
authDomain: '......',
databaseURL: '....',
projectId: '....',
storageBucket: '....',
messagingSenderId: '....'
};
firebase.initializeApp(config);
const database = firebase.database();
export default database;
Help me in this, Thanks.
You have to tell the component to re-render, when there is a change in data. I don't think the functions related to firebase should live outside the component. Instead they should live within the component. You should do something like below. Hope it helps
import React, { Component } from 'react';
import { BootstrapTable, TableHeaderColumn } from 'react-bootstrap-table';
import PageHeader from 'react-bootstrap/lib/PageHeader';
import database from './database';
class Member extends Component {
constructor(props) {
super(props);
this.state = {
text:'',
products: []
};
this.userRef = database.ref('users');
}
componentDidMount() {
this.userRef.on('value', this.gotData, this.errData);
}
gotData = (data) => {
let newProducts = []
const userdata = data.val();
const keys = Object.keys(userdata);
for (let i = 0; i < keys.length; i++) {
const k = keys[i];
newProducts.push({
name: userdata[k].nama, address: userdata[k].address, email: userdata[k].email
});
}
this.setState({products: newProducts});
}
errData = (err) => {
console.log(err);
}
handleClick = (rowKey) => {
alert(this.refs.table.getPageByRowKey(rowKey));
}
render(){
return (
<div>
<div className="col-lg-12">
<PageHeader>Members</PageHeader>
</div>
<BootstrapTable
ref='table'
data={ this.state.products }
pagination={ true }
search={ true }>
<TableHeaderColumn dataField='name' isKey={true} dataSort={true}>Name</TableHeaderColumn>
<TableHeaderColumn dataField='address' dataSort={true}>Address</TableHeaderColumn>
<TableHeaderColumn dataField='email'>Email</TableHeaderColumn>
</BootstrapTable>
</div>
);
}
}
export default Member;
All subscription related code goes into componentDidMount and you have to unsubscribe when the component will unmount.

react-virtualized getting error - TypeError: list.get is not a function

Getting error - TypeError: list.get is not a function
My Parent component :
import TableExample from './TableExample';
// Map Redux state to component props
function mapStateToProps(state) {
return {
dirList: state.filelistReducer.dirList,
showFileViewer: state.sidenavReducer.showFileViewer,
}
}
// Map Redux actions to component props
function mapDispatchToProps(dispatch) {
return {
onDirClick: (path) => { dispatch(actions.fetchFileListAction(path, dispatch)); },
};
}
/**
*
*
* #class FileViewerComponent
* #extends {Component}
*/
class FileListViewComponent extends Component {
constructor(props) {
super(props);
this.state = { width: 0 }
}
render() {
return (
<div>
<div className="col-md-10">
<div className="contentviewdivider" style={{ width: (this.state.width) + 'px' }}></div>
<div className="mainContainer" style={{ width: (this.state.width) + 'px' }}>
<div className="tilerow">
{this.renderList()}
</div>
</div>
</div>
</div>
);
}
renderList() {
return (
<div>
<div className={this.props.showFileViewer}>
<div className='row'>
<TableExample filelist={this.props.dirList} />
</div>
</div>
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(FileListViewComponent);
Now in TableExample.jsx
/** #flow */
import Immutable from 'immutable';
import { List } from 'immutable';
import React, { PropTypes, PureComponent } from 'react';
import ReactDom from 'react-dom';
import { ContentBox, ContentBoxHeader, ContentBoxParagraph } from '../demo/ContentBox'
import { LabeledInput, InputRow } from '../demo/LabeledInput'
import {AutoSizer,Column, Table, SortDirection, SortIndicator} from 'react-virtualized'
import styles from '../../../styles/css/components/tableexample.css'
//import { generateRandomList } from './utils'
export default class TableExample extends PureComponent {
// static contextTypes = {
// list: PropTypes.instanceOf(Immutable.List).isRequired
// };
constructor (props) {
super(props)
this.state = {
disableHeader: false,
headerHeight: 30,
height: 270,
hideIndexRow: false,
overscanRowCount: 10,
rowHeight: 40,
rowCount: 1000,
scrollToIndex: undefined,
sortBy: 'index',
sortDirection: SortDirection.ASC,
useDynamicRowHeight: false
}
this._getRowHeight = this._getRowHeight.bind(this)
this._headerRenderer = this._headerRenderer.bind(this)
this._noRowsRenderer = this._noRowsRenderer.bind(this)
this._onRowCountChange = this._onRowCountChange.bind(this)
this._onScrollToRowChange = this._onScrollToRowChange.bind(this)
this._rowClassName = this._rowClassName.bind(this)
this._sort = this._sort.bind(this)
}
render () {
const {
disableHeader,
headerHeight,
height,
hideIndexRow,
overscanRowCount,
rowHeight,
rowCount,
scrollToIndex,
sortBy,
sortDirection,
useDynamicRowHeight
} = this.state
console.log('render of tableexample');
console.log(this.props);
const list = this.props.filelist;
const sortedList = this._isSortEnabled()
? list
.sortBy(item => item[sortBy])
.update(list =>
sortDirection === SortDirection.DESC
? list.reverse()
: list
)
: list
const rowGetter = ({ index }) => this._getDatum(sortedList, index)
return (
<ContentBox>
<div className="table table-striped">
<AutoSizer disableHeight>
{({ width }) => (
<Table
ref='Table'
disableHeader={disableHeader}
headerClassName={styles.headerColumn}
headerHeight={headerHeight}
height={height}
noRowsRenderer={this._noRowsRenderer}
overscanRowCount={overscanRowCount}
rowClassName={this._rowClassName}
rowHeight={useDynamicRowHeight ? this._getRowHeight : rowHeight}
rowGetter={rowGetter}
rowCount={rowCount}
scrollToIndex={scrollToIndex}
sort={this._sort}
sortBy={sortBy}
sortDirection={sortDirection}
width={width}
>
{!hideIndexRow &&
<Column
label='Index'
cellDataGetter={
({ columnData, dataKey, rowData }) => rowData.index
}
dataKey='index'
disableSort={!this._isSortEnabled()}
width={60}
/>
}
<Column
dataKey='name'
disableSort={!this._isSortEnabled()}
headerRenderer={this._headerRenderer}
width={90}
/>
<Column
width={210}
disableSort
label='The description label is really long so that it will be truncated'
dataKey='random'
className={styles.exampleColumn}
cellRenderer={
({ cellData, columnData, dataKey, rowData, rowIndex }) => cellData
}
flexGrow={1}
/>
</Table>
)}
</AutoSizer>
</div>
</ContentBox>
)
}
_getDatum (list, index) {
// Getting error here : TypeError: list.get is not a function[Learn More]
return list.get(index % list.size)
}
_getRowHeight ({ index }) {
const list = this.props.filelist;
return this._getDatum(list, index).size
}
_headerRenderer ({
columnData,
dataKey,
disableSort,
label,
sortBy,
sortDirection
}) {
return (
<div>
Full Name
{sortBy === dataKey &&
<SortIndicator sortDirection={sortDirection} />
}
</div>
)
}
_isSortEnabled () {
const list= this.props.filelist;
const { rowCount } = this.state
return rowCount <= list.size
}
_noRowsRenderer () {
return (
<div className={styles.noRows}>
No rows
</div>
)
}
_onRowCountChange (event) {
const rowCount = parseInt(event.target.value, 10) || 0
this.setState({ rowCount })
}
_onScrollToRowChange (event) {
const { rowCount } = this.state
let scrollToIndex = Math.min(rowCount - 1, parseInt(event.target.value, 10))
if (isNaN(scrollToIndex)) {
scrollToIndex = undefined
}
this.setState({ scrollToIndex })
}
_rowClassName ({ index }) {
if (index < 0) {
return styles.headerRow
} else {
return index % 2 === 0 ? styles.evenRow : styles.oddRow
}
}
_sort ({ sortBy, sortDirection }) {
this.setState({ sortBy, sortDirection })
}
_updateUseDynamicRowHeight (value) {
this.setState({
useDynamicRowHeight: value
})
}
}
I am getting error inside -
_getDatum (list, index) {
// Getting error here : TypeError: list.get is not a function[Learn More]
return list.get(index % list.size)
}
I am not using immutable list, instead using my own object. If I do
console.log(this.props.filelist) // Object { filelist: Array[12] }
0:Object
absPath:"/home/testmaximumcharactersforfolders123"
created:1490586030000
filename:"testmaximumcharactersforfolders123"
hasChildren:true
isHidden:false
isReadable:true
isWritable:false
modified:1490586030000
owner:"root"
size:4096
type:"FILE_DIR"
I have one more question, as you can see my object structure above what should be my datakey ? As per my understanding using datakey we are referring key name in our object . so should it be datakey="filename" if I want to show filename data in the column ? And is it ok if my object contains other key value pair which I am not going to show in the table ?
Please help...
Screenshot of overlapping :

React setState called multiple times on the same state object

I have the following:
import React from 'react';
import ReactDOM from 'react-dom'
import {render} from 'react-dom';
import Forms from './forms/forms.jsx';
class Option1 extends React.Component {
render () {
return (
<p>Icon 1</p>
)
}
}
class TShirt extends React.Component {
render () {
console.log(this.props.currentState);
return <div className="thsirt">
<h1>{this.props.name}</h1>
<p>{this.props.iconID}</p>
{this.props.optionA ? <Option1 /> : ''}
</div>;
}
}
class Link extends React.Component {
render () {
return (
<li
data-id={this.props.el}
onClick={this.props.onClick}
className={this.props.activeClass}>{this.props.el}
</li>
);
}
}
class Nav extends React.Component {
getComponentID (id) {
switch(id) {
case 'name':
return 1;
break;
case 'color':
return 2;
break;
case 'design':
return 3;
break;
case 'share':
return 4;
break;
}
}
handleClick (event) {
// setting active class
var id = event.target.getAttribute("data-id");
this.props.action(id);
// switching coomponent based on active class
var component = this.getComponentID(id);
this.props.switchComponent(component);
}
render () {
var links = ['name', 'color', 'design', 'share'],
newLinks = [],
that = this;
links.forEach(function(el){
newLinks.push(<Link
onClick={that.handleClick.bind(that)}
activeClass={that.props.active == el ? 'active': ''}
key={el}
el={el}
/>
);
});
return (
<ol>
{newLinks}
</ol>
);
}
}
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
name: '',
color: '',
active: '',
formId: 1,
optionA: {
on: false,
icon_id: '',
option_id: '',
name: ''
}
};
this.setName = this.setName.bind(this);
this.setColor = this.setColor.bind(this);
this.setAtciveNavEl = this.setAtciveNavEl.bind(this);
this.setFormId = this.setFormId.bind(this);
this.setOptionA = this.setOptionA.bind(this);
this.setOptionAVisibility = this.setOptionAVisibility.bind(this);
}
setName (tshirt) {
this.setState({ name:tshirt })
}
setColor (color) {
this.setState({ color:color })
}
setAtciveNavEl (el) {
this.setState({ active:el })
}
setFormId (id) {
this.setState({ formId:id })
}
setOptionA (iconID, iconName) {
this.setState({
optionA:
{
icon_id: iconID,
name: iconName
}
})
}
setOptionAVisibility (onOff, optionID) {
this.setState({
optionA:
{
option_id: optionID,
on: onOff
}
})
}
render () {
return (
<section className={this.state.color}>
<Nav
active={this.state.active}
action={this.setAtciveNavEl}
switchComponent={this.setFormId}
/>
<TShirt
name={this.state.name}
icons={this.state.options}
optionA={this.state.optionA.on}
currentState={this.state}
/>
<Forms
name={this.state.name}
action={this.setName}
colorVal={this.setColor}
activeNav={this.setAtciveNavEl}
switchComponent={this.setFormId}
formID={this.state.formId}
setOptionA={this.setOptionA}
setOptionAVisibility={this.setOptionAVisibility}
/>
</section>
);
}
}
render(<App/>, document.getElementById('app'));
I need to populate this object at different times like this:
setOptionA (iconID, iconName) {
this.setState({
optionA:
{
icon_id: iconID,
name: iconName
}
})
}
setOptionAVisibility (onOff, optionID) {
this.setState({
optionA:
{
option_id: optionID,
on: onOff
}
})
}
The problem I have is taht when I console.log my state at:
class TShirt extends React.Component {
render () {
console.log(this.props.currentState);
return <div className="thsirt">
<h1>{this.props.name}</h1>
<p>{this.props.iconID}</p>
{this.props.optionA ? <Option1 /> : ''}
</div>;
}
}
after all my click events it seems like I loose the "on" and "option_id" from the optionA object.
Does calling setState on the same object override the previous setState?
If you are writing ES2015, you can use the spread operator to copy the whole object and just modify one of it's properties:
setOptionAVisibility (onOff, optionID) {
this.setState({
optionA:
{
...this.state.optionA,
option_id: optionID,
on: onOff
}
})
}
Can be very useful when modifying single properties of complex objects on the state tree.

Resources