Reputation: 6673
I have the following data:
var data = [
["The Lord of the Rings", "J. R. R. Tolkien", "English", "1954-1955", "150 million"],
["Le Petit Prince (The Little Prince)", "Antoine de Saint-Exupéry", "French", "1943", "140 million"],
["Harry Potter and the Philosopher's Stone", "J. K. Rowling", "English", "1997", "107 million"],
["And Then There Were None", "Agatha Christie", "English", "1939", "100 million"],
["Dream of the Red Chamber", "Cao Xueqin", "Chinese", "1754-1791", "100 million"],
["The Hobbit", "J. R. R. Tolkien", "English", "1937", "100 million"],
["She: A History of Adventure", "H. Rider Haggard", "English", "1887", "100 million"],
];
and I use these to render a table with a row for each item (books with their data). For learning purposes I want to add a new item to the array and I do it with this code:
var valueToPush = new Array();
valueToPush[0]="Frodi societarie";
valueToPush[1]="Lelio Faieta";
valueToPush[2]="Italiano";
valueToPush[3]="2004";
valueToPush[4]="10";
var myTimer = setTimeout(function() {data.push(valueToPush); console.log(data);}, 5000);
My goal is then to have the new line added into the table. The table is rendered with this code:
var Ex = ReactDOM.render(
React.createElement(Excel, {
headers: headers,
initialData: data,
}),
document.getElementById("app")
);
What is the next step to get the table re-rendered? The following is my full code so far:
var Excel = React.createClass({
displayName: 'Excel',
propTypes: {
headers: React.PropTypes.arrayOf(
React.PropTypes.string
),
initialData: React.PropTypes.arrayOf(
React.PropTypes.arrayOf(
React.PropTypes.string
)
),
},
getInitialState: function() {
return {
data: this.props.initialData,
sortby: null,
descending: false,
edit: null, // [row index, cell index],
search: false,
};
},
_sort: function(e) {
var column = e.target.cellIndex;
var data = this.state.data.slice();
var descending = this.state.sortby === column && !this.state.descending;
data.sort(function(a, b) {
return descending
? (a[column] < b[column] ? 1 : -1)
: (a[column] > b[column] ? 1 : -1);
});
this.setState({
data: data,
sortby: column,
descending: descending,
});
},
_showEditor: function(e) {
this.setState({edit: {
row: parseInt(e.target.dataset.row, 10),
cell: e.target.cellIndex,
}});
},
_save: function(e) {
e.preventDefault();
var input = e.target.firstChild;
var data = this.state.data.slice();
data[this.state.edit.row][this.state.edit.cell] = input.value;
this.setState({
edit: null,
data: data,
});
},
_preSearchData: null,
_toggleSearch: function() {
if (this.state.search) {
this.setState({
data: this._preSearchData,
search: false,
});
this._preSearchData = null;
} else {
this._preSearchData = this.state.data;
this.setState({
search: true,
});
}
},
_search: function(e) {
var needle = e.target.value.toLowerCase();
if (!needle) {
this.setState({data: this._preSearchData});
return;
}
var idx = e.target.dataset.idx;
var searchdata = this._preSearchData.filter(function(row) {
return row[idx].toString().toLowerCase().indexOf(needle) > -1;
});
this.setState({data: searchdata});
},
_download: function(format, ev) {
var contents = format === 'json'
? JSON.stringify(this.state.data)
: this.state.data.reduce(function(result, row) {
return result
+ row.reduce(function(rowresult, cell, idx) {
return rowresult
+ '"'
+ cell.replace(/"/g, '""')
+ '"'
+ (idx < row.length - 1 ? ',' : '');
}, '')
+ "\n";
}, '');
var URL = window.URL || window.webkitURL;
var blob = new Blob([contents], {type: 'text/' + format});
ev.target.href = URL.createObjectURL(blob);
ev.target.download = 'data.' + format;
},
render: function() {
return (
React.DOM.div(null,
this._renderToolbar(),
this._renderTable()
)
);
},
_renderToolbar: function() {
return React.DOM.div({className: 'toolbar'},
React.DOM.button({
onClick: this._toggleSearch,
}, 'Search'),
React.DOM.a({
onClick: this._download.bind(this, 'json'),
href: 'data.json',
}, 'Export JSON'),
React.DOM.a({
onClick: this._download.bind(this, 'csv'),
href: 'data.csv',
}, 'Export CSV')
);
},
_renderSearch: function() {
if (!this.state.search) {
return null;
}
return (
React.DOM.tr({onChange: this._search},
this.props.headers.map(function(_ignore, idx) {
return React.DOM.td({key: idx},
React.DOM.input({
type: 'text',
'data-idx': idx,
})
);
})
)
);
},
_renderTable: function() {
return (
React.DOM.table(null,
React.DOM.thead({onClick: this._sort},
React.DOM.tr(null,
this.props.headers.map(function(title, idx) {
if (this.state.sortby === idx) {
title += this.state.descending ? ' \u2191' : ' \u2193';
}
return React.DOM.th({key: idx}, title);
}, this)
)
),
React.DOM.tbody({onDoubleClick: this._showEditor},
this._renderSearch(),
this.state.data.map(function(row, rowidx) {
return (
React.DOM.tr({key: rowidx},
row.map(function(cell, idx) {
var content = cell;
var edit = this.state.edit;
if (edit && edit.row === rowidx && edit.cell === idx) {
content = React.DOM.form({onSubmit: this._save},
React.DOM.input({
type: 'text',
defaultValue: cell,
})
);
}
return React.DOM.td({
key: idx,
'data-row': rowidx,
}, content);
}, this)
)
);
}, this)
)
)
);
}
});
var headers = [
"Book", "Author", "Language", "Published", "Sales"
];
var data = [
["The Lord of the Rings", "J. R. R. Tolkien", "English", "1954-1955", "150 million"],
["Le Petit Prince (The Little Prince)", "Antoine de Saint-Exupéry", "French", "1943", "140 million"],
["Harry Potter and the Philosopher's Stone", "J. K. Rowling", "English", "1997", "107 million"],
["And Then There Were None", "Agatha Christie", "English", "1939", "100 million"],
["Dream of the Red Chamber", "Cao Xueqin", "Chinese", "1754-1791", "100 million"],
["The Hobbit", "J. R. R. Tolkien", "English", "1937", "100 million"],
["She: A History of Adventure", "H. Rider Haggard", "English", "1887", "100 million"],
];
this.state(data);
var myTimer = setTimeout(function() {this.setState([this.state,["Frodi","Lelio","Italiano","2004","10"]]); console.log(data);}, 5000);
var Ex = ReactDOM.render(
React.createElement(Excel, {
headers: headers,
initialData: data,
}),
document.getElementById("app")
);
Upvotes: 0
Views: 209
Reputation: 3207
you have to put your data in a state, then whenever you update the state a rerender will happen
const [data, setData] = useState([
["The Lord of the Rings", "J. R. R. Tolkien", "English", "1954-1955", "150 million"],
["Le Petit Prince (The Little Prince)", "Antoine de Saint-Exupéry", "French", "1943", "140 million"],
["Harry Potter and the Philosopher's Stone", "J. K. Rowling", "English", "1997", "107 million"],
["And Then There Were None", "Agatha Christie", "English", "1939", "100 million"],
["Dream of the Red Chamber", "Cao Xueqin", "Chinese", "1754-1791", "100 million"],
["The Hobbit", "J. R. R. Tolkien", "English", "1937", "100 million"],
["She: A History of Adventure", "H. Rider Haggard", "English", "1887", "100 million"],
]);
setData([..data, ["Frodi societarie", "Lelio Faieta", "Italiano", "2004", "10"]);
UPDATE
As you are using react 15 you cannot use hooks:
import React from "react";
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
books: [
[
"The Lord of the Rings",
"J. R. R. Tolkien",
"English",
"1954-1955",
"150 million"
],
[
"Le Petit Prince (The Little Prince)",
"Antoine de Saint-Exupéry",
"French",
"1943",
"140 million"
],
[
"Harry Potter and the Philosopher's Stone",
"J. K. Rowling",
"English",
"1997",
"107 million"
],
[
"And Then There Were None",
"Agatha Christie",
"English",
"1939",
"100 million"
],
[
"Dream of the Red Chamber",
"Cao Xueqin",
"Chinese",
"1754-1791",
"100 million"
],
["The Hobbit", "J. R. R. Tolkien", "English", "1937", "100 million"],
[
"She: A History of Adventure",
"H. Rider Haggard",
"English",
"1887",
"100 million"
]
]
};
}
componentDidMount() {
setTimeout(() => {
this.setState({
books: [
...this.state.books,
["Frodi societarie", "Lelio Faieta", "Italiano", "2004", "10"]
]
});
}, 5000);
}
render() {
return (
<ul>
{this.state.books.map((book, index) => (
<li key={index}>{book[0]}</li>
))}
</ul>
);
}
}
export default App;
Here the codesandbox: https://codesandbox.io/s/priceless-leftpad-3338g
Upvotes: 2
Reputation: 625
You should always use setState
to trigger re-render in case of class based components and method from useState
in case of functional component.
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
name: 'my name'
}
}
clickHandler() {
// 1st case
this.setState({name: 'new name'})
// 2nd case
//this.state.name = 'new name'
}
render() {
return (
<div>
{this.state.name}
<button onClick={this.clickHandler.bind(this)} > change
Name </button>
</div>
)
}
}
ReactDOM.render(<App />, document.querySelector("#app"))
Toggle between 1st and 2nd case to see how this works
Upvotes: -1
Reputation: 1005
Please go through react official documentation, It has everything in it. BTW
this.setState({
tableData: [
...data,
valueToPush
]
})
Upvotes: 1