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.
Related
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
I have state data in my index.js page that is being sent to my details.js page via the Link component built into gatsby. From my details.js page, I am trying to send data to my component ChartData.js.
In details.js I can access my information by using {props.location.state.x}. Now I need the same data to be sent to my component and what I did was put Stock (Stock is the class name in ChartData.js) the comonent and set 'symbol' equal to the way I would reference data just like this: {<Stock symbol={props.location.state.symbol}/>}
Now under ChartData/.js when I try to reference symbol I get the error 'symbol is not defined'. Not sure if I am messing up the syntax of passing it or if you cannot do it this way.
index.js:
import React from "react"
import { Link } from "gatsby"
import axios from "axios"
import "../css/style.css"
import Layout from "../components/layout"
import { symbol } from "prop-types"
//import Stock from "../components/ChartData"
//import Characters from "../components/ChartData"
export default class index extends React.Component {
state = {
companyName: "",
previousClose: "",
marketCap: "",
change: "",
symbol: "",
topStocks: [],
Yearweekhigh: "",
Yearweeklow: "",
avgTotalVolume: "",
peRatio: "",
}
clickHandler = (event) => {
if (event.keyCode === 13) {
const query = event.target.value;
const API_KEY = '******************';
axios.get(`https://cloud.iexapis.com/stable/stock/${query}/quote?token=${API_KEY}`)
.then(res => {
const companyName = res.data['companyName'];
this.setState({ companyName })
const previousClose = res.data['previousClose'];
this.setState({ previousClose })
const marketCap = res.data['marketCap'];
this.setState({ marketCap })
const change = res.data['change'];
this.setState({ change })
const symbol = res.data['symbol'];
this.setState({ symbol })
const Yearweekhigh = res.data['week52High'];
this.setState({ Yearweekhigh })
const Yearweeklow = res.data['week52Low'];
this.setState({ Yearweeklow })
const avgTotalVolume = res.data['avgTotalVolume'];
this.setState({ avgTotalVolume })
const peRatio = res.data['peRatio'];
this.setState({ peRatio })
const open = res.data['open'];
this.setState({ open })
const high = res.data['high'];
this.setState({ high })
const low = res.data['low'];
this.setState({ low })
const volume = res.data['volume'];
this.setState({ volume })
})
}
}
render() {
return (
<Layout>
<div class = "main-div">
<input type="search" class="main-search" onKeyDown={event => this.clickHandler(event)}/>
<table>
<tr>
<th>Ticker-Symbol</th>
<th>Market Cap</th>
<th>Previous Close</th>
</tr>
<tr>
<td>
<Link to='/details/' state={{
setState: this.state.symbol,
companyName: this.state.companyName,
previousClose: this.state.previousClose,
marketCap: this.state.marketCap,
change: this.state.change,
Yearweekhigh: this.state.Yearweekhigh,
Yearweeklow: this.state.Yearweeklow,
avgTotalVolume: this.state.avgTotalVolume,
peRatio: this.state.peRatio,
open: this.state.open,
high: this.state.high,
low: this.state.low,
volume: this.state.volume,
symbol: this.state.symbol
}}>
{this.state.symbol}</Link>
</td>
<td>{this.state.marketCap}</td>
<td>{this.state.previousClose}</td>
</tr>
</table>
</div>
<div>
{
this.state.topStocks.length && this.state.topStocks.map(stock => (
<h1>{stock.symbol}</h1>
))
}
</div>
</Layout>
)
}
}
details.js
//import { Link } from "gatsby"
import axios from 'axios';
import React, { useEffect, useState } from 'react';
import Layout from '../components/layout';
import "../css/style.css"
import Stock from "../components/ChartData"
const Details = props => {
const [yourState, setYourState] = useState('');
useEffect(() => {
}, []);
return <Layout>
<div>
<h1 class="details-company-name">{props.location.state.companyName}</h1>
<div class = "details-div">
<div class="details-div-1">
<p>Open <h2>{props.location.state.open}</h2> </p>
<p>High <h2>{props.location.state.high}</h2> </p>
<p>Low <h2>{props.location.state.low}</h2> </p>
<p>52 WK HIGH <h2>{props.location.state.Yearweekhigh}</h2> </p>
<p>52 WK LOW <h2>{props.location.state.Yearweeklow}</h2> </p>
<p>{props.location.state.symbol}</p>
</div>
<div class="details-div-2">
<p>VOLUME <h2>{props.location.state.volume}</h2></p>
<p>AVG VOL <h2>{props.location.state.avgTotalVolume}</h2> </p>
<p>MKT CAP <h2>{props.location.state.marketCap}</h2></p>
<p>P/E RATIO <h2>{props.location.state.peRatio}</h2></p>
<p>DIV/YIELD</p>
</div>
</div>
</div>
<Stock symbol={props.location.state.symbol}/>
</Layout>;
};
export default Details;
ChartData.js
import React from 'react'
import Plot from 'react-plotly.js'
class Stock extends React.Component {
constructor(props) {
super(props);
this.state = {
stockChartXValues: [],
stockChartYValues: [],
};
}
componentDidMount() {
this.fetchStock();
}
fetchStock() {
const pointerToThis = this;
const API_KEY = '*****************';
let API_CALL = `https://cloud.iexapis.com/stable/${symbol}/aapl/chart/5y?token=${API_KEY}`;
let stockChartXValuesFunction = [];
let stockChartYValuesFunction = [];
fetch(API_CALL)
.then(function (response) {
return response.json();
})
.then(function (data) {
for (var x in data) {
stockChartXValuesFunction.push(x);
stockChartYValuesFunction.push(
data[x]['uOpen']
);
pointerToThis.setState({
stockChartXValues: stockChartXValuesFunction,
stockChartYValues: stockChartYValuesFunction,
});
}
})
}
render() {
return (
<div>
<Plot
data={[
{
x: this.state.stockChartXValues,
y: this.state.stockChartYValues,
type: "scatter",
mode: "lines+markers",
marker: {color: "red"}
},
]}
layout={{ width: 720, height: 440, title: "A Fancy Plot"}}
/>
</div>
)
}
}
export default Stock
You have a few issues there:
Everything you pass through props must be received by the child component accessing to those props. So instead of symbol, you must this.props.symbol. Since you are not destructuring your props:
let API_CALL =
`https://cloud.iexapis.com/stable/${this.props.symbol}/aapl/chart/5ytoken=${API_KEY}`;
To avoid wrong or empty calls, I would ensure that you have your props properly set and I would add a condition like:
componentDidMount() {
if(props.symbol) this.fetchStock();
}
You may need to add a constructor in your file to gather props:
constructor(props) {
super(props);
this.state = {}; // remove if not needed
}
I've been following a react tutorial by Wes Bos and I can't seem to get some of the state to persist using the firebase database. My 'order' state seems to persist, but the 'fishes' state in my inventory doesn't.
Specifically, I can see the changes made to 'fishes' once I change them in the react app, but if I exit the store and come back in, the order persists but the 'fishes' do not.
base.js
import Rebase from 're-base';
import * as firebase from 'firebase';
const app = firebase.initializeApp({
apiKey: "XXXXXXXXX",
authDomain: "XXXXXXXX",
databaseURL: "XXXXXXXXXXXXXXXXX",
projectId: "XXXXXXXXXXXX",
storageBucket: "XXXXXXXXXXXXXXXXX",
});
const base = Rebase.createClass(app.database());
export default base;
app.js
import React from 'react';
import Header from './Header';
import Order from './Order';
import Inventory from './Inventory';
import Fish from './Fish';
import sampleFishes from '../sample-fishes';
import base from '../base';
import PropTypes from 'prop-types';
import * as firebase from 'firebase';
export default class App extends React.Component {
constructor() {
super();
this.addFish = this.addFish.bind(this);
this.loadSamples = this.loadSamples.bind(this);
this.addToOrder = this.addToOrder.bind(this);
this.updateFish = this.updateFish.bind(this);
this.removeFish = this.removeFish.bind(this);
this.removeFromOrder = this.removeFromOrder.bind(this);
this.state = {
fishes: {},
order: {},
};
}
componentDidMount() {
this.FishRef = base.syncState(`${this.props.match.params.storeId}/fishes`,
{
context: this,
state: 'fishes'
});
}
componentDidMount() {
this.OrderRef = base.syncState(`${this.props.match.params.storeId}/order`,
{
context: this,
state: 'order'
});
}
componentWillUnmount() {
base.removeBinding(this.FishRef);
base.removeBinding(this.OrderRef);
}
addFish(fish) {
const fishes = {...this.state.fishes};
const timestamp = Date.now();
fishes[`fish-${timestamp}`] = fish;
this.setState({ fishes });
}
removeFish(key) {
const fishes = {...this.state.fishes};
fishes[key] = null;
this.setState({ fishes });
}
updateFish(key, updatedFish) {
const fishes = {...this.state.fishes};
fishes[key] = updatedFish;
this.setState({ fishes });
}
loadSamples() {
this.setState({
fishes: sampleFishes
});
}
addToOrder(key) {
const order = {...this.state.order};
order[key] = order[key] + 1 || 1;
this.setState({ order });
}
removeFromOrder(key){
const order = {...this.state.order};
delete order[key];
this.setState({ order });
}
render() {
return(
<div className="catch-of-the-day">
<div className="menu">
<Header tagline="Fresh seafood market"/>
<ul className="list-of-fishes">
{Object
.keys(this.state.fishes)
.map(key => <Fish key={key}
details={this.state.fishes[key]}
addToOrder={this.addToOrder}
index={key}
/>)
}
</ul>
</div>
<Order fishes={this.state.fishes}
order={this.state.order}
removeFromOrder={this.removeFromOrder}/>
<Inventory addFish={this.addFish}
loadSamples={this.loadSamples}
fishes = {this.state.fishes}
updateFish = {this.updateFish}
removeFish = {this.removeFish}/>
</div>
);
}
}
App.propTypes = {
match: PropTypes.object.isRequired
}
you declared componentDidMount twice , here :
componentDidMount() {
this.FishRef = base.syncState(`${this.props.match.params.storeId}/fishes`,
{
context: this,
state: 'fishes'
});
}
componentDidMount() {
this.OrderRef = base.syncState(`${this.props.match.params.storeId}/order`,
{
context: this,
state: 'order'
});
}
this mean the first will execute and the second will not or the other way around .
fix this by add the body of second the body of the first like this :
componentDidMount() {
this.FishRef = base.syncState(`${this.props.match.params.storeId}/fishes`,
{
context: this,
state: 'fishes'
});
this.OrderRef = base.syncState(`${this.props.match.params.storeId}/order`,
{
context: this,
state: 'order'
});
}
This is my App.js and i have set my database in firebase. All the messages which i enter all display in database also.But i need to automatically send message back to me . so any one knows how to do that please help. Thank you.
import React, { Component } from 'react';
import MessagePane from './MessagePane';
import ChannelList from './ChannelList';
import { getMessages, getChannels, saveMessage, onNewMessage } from './remote_storage1';
import './App.css';
class App extends Component {
constructor() {
super();
this.state = {
messages: [],
channels: [],
selected_channel_id: null
};
this.onSendMessage = this.onSendMessage.bind(this);
this.onChannelSelect = this.onChannelSelect.bind(this);
this.filteredMessages = this.filteredMessages.bind(this);
}
componentDidMount() {
getMessages().then(messages => this.setState({messages}));
getChannels().then(channels => this.setState({channels, selected_channel_id: channels[0].id}));
onNewMessage(new_message => {
const messages = [...this.state.messages, new_message];
this.setState({messages});
});
}
onSendMessage(author, text) {
const new_message = {
id: this.state.messages[this.state.messages.length - 1].id + 1,
author,
text,
channel_id: this.state.selected_channel_id
};
saveMessage(new_message);
const messages = [...this.state.messages, new_message];
this.setState({messages});
}
onChannelSelect(id) {
this.setState({ selected_channel_id: id });
}
filteredMessages() {
return this.state.messages.filter(({channel_id}) => channel_id === this.state.selected_channel_id);
}
render() {
return (
<div className="App">
<ChannelList
channels={this.state.channels}
selectedChannelId={this.state.selected_channel_id}
onSelect={this.onChannelSelect}
/>
<MessagePane messages={this.filteredMessages()} onSendMessage={this.onSendMessage} />
</div>
);
}
}
export default App;
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;