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
Related
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 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;
Problem
So as the title said i've this issue in a todoapp. i checked if i had some typo like react instead of React and it seems to be alright.
Before post something i checked:
First post stackoverflow
Second post stackoverflow
but i cannot find a solution
Code
App.js
import React, {Component} from 'react';
import Form from './Components/Form';
import Footer from './Components/Footer';
import Header from './Components/Header';
class App extends React{
constructor(props) {
this.state = {
todoValue: "",
filterType: "All",
todos: [],
}
}
handleChange = (event) => {
this.setState({
todoValue: event.target.value,
})
}
handleClick = (event) => {
event.preventDefault();
if (this.state.todoValue !== "") {
const todo = {
id: Date.now(),
text: this.state.todoValue,
done: false,
}
this.setState({
todoValue: "",
todos: [todo, ...this.state.todos],
})
}
}
handleToggle = (id) => {
this.setState((prevState) => {
return {
todos: prevState.todos.map((item, i) => {
if (item.id === id) {
return {
...item,
done: !prevState.todos[i].done,
}
}
return item;
})
}
})
}
handleDelete = (id) => {
this.setState({
todos: this.state.todos.filter(item => item.id !== id)
})
}
deleteCompleted = () => {
this.setState({
todos: this.state.todos.filter(item => !item.done)
})
}
getVisibleTodos = () => {
const filterType = this.state.filterType;
let filterState = null;
switch (filterType) {
case "Completed":
return filterState = this.state.todos.filter(item => item.done);
case "Active":
return filterState = this.state.todos.filter(item => !item.done);
case "Originals":
return filterState = this.state.todos.filter(item => !item.done);
case "New":
return filterState = this.state.todos.filter(item => !item.done);
default:
return filterState = this.state.todos;
}
}
setActiveFilter = (text) => {
this.setState({
filterType: text,
})
}
render() {
return (
<div className="container">
<Header countTodo={this.state.todos.length}/>
<Form handleDelete={this.handleDelete}
handleToggle={this.handleToggle}
handleClick={this.handleClick}
handleChange={this.handleChange}
todoValue={this.state.todoValue}
todos={this.getVisibleTodos()}/>
<Footer setActiveFilter={this.setActiveFilter}
deleteCompleted={this.deleteCompleted}
filter={this.state.filterType}/>
</div>
)
}
}
export default App;
Header.js
import React from 'react';
class Header extends React.Component {
render() {
return (
<header className="header">
<h3>All To-Do {this.props.countTodo}</h3>
</header>
)
}
}
export default Header;
Form.js
import React, {Component} from'react';
import Todo from './Todo';
class Form extends React {
render() {
return (
<form className="form">
<input type="text"
className="form__input"
placeholder="Items"
onChange={this.props.handleChange}
value={this.props.todoValue}
/>
<button
className="form__button"
type="submit"
onClick={this.props.handleClick}>╋</button>
<Todo
todos={this.props.todos}
handleToggle={this.props.handleToggle}
handleDelete={this.props.handleDelete}
/>
</form>
)
}
}
export default Form;
and the last modul is Todo.js
import React, {Component} from 'react';
class Todo extends React{
render() {
return (
<ul className="todos-list">
{
this.props.todos.map((item) => {
return (
<li className="todo-item"
key={item.id} onClick={() => this.props.handleToggle(item.id)}>
<span
className={item.done ? "todo-item__name disabled" : "todo-item__name"}>
{item.text}
</span>
<span
className="todo-item__delete-button"
onClick={() => this.props.handleDelete(item.id)}>
×
</span>
</li>
)
})
}
</ul>
)
}
}
export default Todo;
You class should extend from Component that you're importing from react library.
It should be either
class App extends Component{}
or if you didn't import Component then
class App extends React.Component{}
You haven't extended your App component correctly
class App extends React{ // error here
constructor(props) {
this.state = {
todoValue: "",
filterType: "All",
todos: [],
}
}
Extend it from React.Component
class App extends React.Component {
constructor(props) {
super(props); // use super here
this.state = {
todoValue: "",
filterType: "All",
todos: [],
}
}
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;
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.