Data does not display right in table - javascript

I'm trying to display data in the table, but for some reasons appears empty fields. I think the issue is that firstly is looking deaths - fills the elements and cases becomes empty. Tried to do in many different ways. In some ways all data are just pulled in one column, in other ways the data just go in rows. Tryied to use lodash as well.
Current code:
<table className="table">
<tr>
<th>Cases</th>
<th>Deaths</th>
</tr>
{_.map(countryData, (item, key) => {
if (item.indicator === "cases") {
return (
<tr>
<td>{item.weekly_count}</td>
<td></td>
</tr>
);
} else {
return (
<tr>
<td>{item.weekly_count}</td>
</tr>
);
}
})}
</table>
Also tried in this way(still empty fields):
{countryData.map((value, key) => {
return (
<tr>
<td>
{value.indicator === "cases" ? value.weekly_count : null}
</td>
<td>
{value.indicator === "deaths" ? value.weekly_count : null}
</td>
</tr>
);
})}
My data from console.log:
Data
Expected result: expected result
Example of issue: Issue
countryData: This data comes after selecting the specific country

The map function is working just fine. The problem is with the object countryData. The object currently does not contain an array. Please make sure the object looks like:
countryData = [{indicator:"cases", weekly_count: xx}, {indicator:"deaths", weekly_count: yy}.....]
I have only used two fields inside each object, you may add more objects according to your requirement.
In order to view cases and deaths as separate columns, please add an empty cell before displaying "deaths".
{_.map(countryData, (item, key) => {
if (item.indicator === "cases") {
return (
<tr>
<td>{item.weekly_count}</td>
<td></td>
</tr>
);
} else {
return (
<tr>
<td></td>
<td>{item.weekly_count}</td>
</tr>
);
}
})}

Related

Render Table <tr> tag based on condition in ReactJs within map loop

I need to render <tr> start and close it, based on a condition:
{grid.map((item, index) => {
return <React.Fragment key={index}>
{item.x === 0 ? <tr/> : ""}
<td id={`td_${item.x}_${item.y}`}>
{item.name}
</td>
</React.Fragment>
})}
Above code rendering all <td> tag outside of <tr> tag, but I want all <td> in <tr> tag.
In this code, I want <tr> start when item.x === 0 and need to render </tr> end in bottom this loop.
{grid.map((item, index) => {
return <React.Fragment key={index}>
{item.x === 0 ? <tr> : ""}
<td id={`td_${item.x}_${item.y}`}>
{item.name}
</td>
{item.x === 0 ? </tr> : ""}
</React.Fragment>
})}
This code showing error in jsx syntax error.
React component trees aren't HTML strings, they're object trees. You need to have a tr object, provide it with a bunch of td children, and then switch to a new tr object and provide its children to it.
Ideally, change how you're storing grid so that it contains the rows, with child objects/arrays for the cells.
If you can't do that, you can do it on the fly:
const rows = [];
let children = [];
for (const item of grid) {
if (grid.x === 0 && children.length) {
rows.push(children);
children = [];
}
children.push(item);
}
if (children.length) {
rows.push(children);
}
Then to render:
{rows.map((children, index) => (
<tr key={index}>
{children.map(item =>
<td id={`td_${item.x}_${item.y}`}>
{item.name}
</td>
)}
</tr>
))}
You'll want to double-check that for minor typos, etc., but it's the fundamental idea: Build an array of rows, with arrays of cells inside.

ReactJs: Displaying the values inside of a state object

I am trying to display the values inside a state object:
I have tried two methods:
Method 1:
<tbody>
{Object.keys(this.state.operationSavInformation).map(
function(key, index) {
return (
<tr key={key}>
<td>{`${key}:`}</td>
<td>
<strong>
{this.state.operationSavInformation[key]}
</strong>
</td>
</tr>
);
}
)}
</tbody>
Method 2:
<tbody>
{Object.keys(this.state.operationSavInformation).forEach(
function(key) {
var value = this.state.operationSavInformation[key];
return (
<tr key={key}>
<td>{`${key}:`}</td>
<td>
<strong>value</strong>
</td>
</tr>
);
}
)}
</tbody>
Both give this error:
TypeError: Cannot read property 'state' of undefined
Unfortunately, these are the only two ways I've found to map over an object values in javaScript. This would work if the object was defined normally. However the problem here is that this is not accessible inside map or forEach, that's why I get the error.
Just grab a reference to it outside the predicate function, like this:
const data = this.state.operationSavInformation
Object.keys(data).map(key => (<tr key={key}>
<td>{`${key}:`}</td>
<td>
<strong>
{data[key]}
</strong>
</td>
</tr>
))

Dynamically Creating Table Rows With React

I am trying to create a Table using React and React-Bootstrap that has a custom number of table rows. The table is supposed to store data about player statistics of a certain video game, and based on the video game the statistics may change, thus the number of rows and titles of these rows must be able to dynamically change as well. I wanted to create an array in the state that held the list of current statistics, then map this array to a element using the map function and render the table. However, after trying several approaches I can't get any of the custom input to render. Below is the code :
Class Structure
class Statistics extends Component {
constructor(props) {
super(props)
this.state = {
game: '',
player_names: [],
positions: [],
stat_categories: [
'kills',
'deaths',
'assists'
]
}
}
renderTableRows(array) {
return (
<tr>
<th> NAME </th>
<th> TEAM </th>
<th> POSITION </th>
{ array.map(item => {
console.log(item)
<th key={item}> {item} </th>
})
}
</tr>
)
}
render() {
const columnLength = this.state.player_names.length
const statCols = this.state.stat_categories
return (
<div>
<MyNav url={this.props.location.pathname} />
<Table responsive striped bordered hover>
<thead>
{ this.renderTableRows(statCols) }
</thead>
</Table>
</div>
)
}
}
The console also properly logs the data in state (kills, deaths, assists) -- so the issue is when rendering the element. Any help would be appreciated!
You have no return statement in your map function, inside of renderTableRows.
When using ES6 arrow functions, you can either:
Return data directly without a return statement
(args) => (returnedData);
Or add some logic instead of just returning directly,
(args) => {
// Logic here
return returnedData
}
In the second case you'll need a return statement, because you are logging, if you choose to remove logging, go the first way.
Also, please post the code directly in your question, as using an image makes it less readable and not indexed by search engines.
You have to render each item in separate trs, not as a series of ths
renderTableCols(array) {
return array.map(item => <th>{item}</th>)
}
renderTableColValues(item, cols) {
return cols.map(col => <td>{item[col]}</td>)
}
renderTableRows(array) {
return array.map(item =>
<tr>
<td>{item.name}</td>
<td>{item.team}</td>
<td>{item.position}</td>
{this.renderTableColValues(item, this.cols)}
</tr>
);
}
render() {
return (
<Table>
<thead>
<tr>
<th>NAME</th>
<th>TEAM</th>
<th>POSITION</th>
{this.renderTableCols(this.cols)}
</tr>
</thead>
<tbody>
{this.renderTableRows(items)}
</tbody>
</Table>
);
}
More on tables https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table
I will give you a similar answer of what youre encoutering but its kinda different approach with a excelent solution
So, you are trying to create a dynamic table but youre making table rows static, what i did was letting the table to receive arrays of head and data and then create as many rows or datas that are required.
heres the code
export function objectIntoTableData(object) {
return Object.values(object).map((data, index) => {
return <td key={index}>{data}</td>;
});
}
You must change this index to (value,index) => , thats just my use
tableRows(data) {
return data.map(value => {
return <tr key={value.index}>{objectIntoTableData(value)}</tr>;
});
}
<thead>
<tr>
{head.map((value, index) => {
return <th key={index}>{value}</th>;
})}
</tr>
</thead>
<tbody>{this.tableRows(data)}</tbody>
Rather use a id or index inside your object since the index callback of the map function, its unsafe to use for the keys.
<ReactTableUse
head={["#", "Cell1", "Cell2", "Cell3"]}
data={[{id:1, test:1},{id:2, test:2}]}
/>
Rules:
When your state changes, render method of a class based component will be called.
Question: Who will change the state? will it grow inside the component ? What is your problem ? your are not being able to render anything ? or statistics is not dynamically rendering ? if you want to change it dynamically , you need to change the state first.

How to get react to update when calling a method from JSX?

I have a table in my jsx that renders a league table. I want to now show the "form" of each team. i.e. the last 5 games.
I have a method that works this out (called form)
const LeagueTable = ({ teams, form }) => (
<table className="leagueTable">
<thead>
<tr className="tableRow">
<th>#</th>
<th>Name</th>
<th>P</th>
<th>W</th>
<th>D</th>
<th>L</th>
<th>F</th>
<th>A</th>
<th>GD</th>
<th>Pts</th>
<th>Form</th>
</tr>
</thead>
<tbody>
{teams.sort((a, b) => (
(b.points) - (a.points)
)).map((team, index) => (
<tr key={index} className="tableRow">
<td className="stats">{index + 1}</td>
<td className="stats">{team.name}</td>
<td className="stats">{team.won + team.lost + team.drawn}</td>
<td className="stats">{team.won}</td>
<td className="stats">{team.drawn}</td>
<td className="stats">{team.lost}</td>
<td className="stats">{team.goalsScored}</td>
<td className="stats">{team.goalsAgainst}</td>
<td className="stats">{team.goalsScored - team.goalsAgainst}</td>
<td className="stats">{team.points}</td>
<td className="stats">{form(team)}</td>
</tr>
))}
</tbody>
</table>
);
this is the method:
form = (team) => {
let lastFiveMatches;
return team && team.matches ?
lastFiveMatches = Object.values(this.props.teams.find(t => t.name === team.name).matches).sort(this.compare).reverse().slice(0, 5).map((match) => {
if(match.winner === team.name){
return 'W ';
}
else if(match.winner !== team.name){
return 'L ';
}
else {
return 'D ';
}
})
:
'---'
}
basically it all works but since adding this method to my table, it only updates my table on refresh rather than instantly (which is what it was doing before)
can anyone explain why it is doing this and how I can change it back?
when I get rid of <td className="stats">{form(team)}</td> it instantly works again so I know this method call is the problem
I have tried adding this.forceUpdate() and this.setState(this.state) to force a re-render but it looks like this causes react to blow up and I get the cannot update during an existing state transition error.
The way you are adding this form function will cause you a lot of pain.
Even though you are saying it works, the this.props... inside the function is not valid.
If you want it to work, what I would do is:
you will need to define compare and not reference this inside the function
const compare = ()=>{'whatever'}
the form code:
const form = (team, teams) => {
let lastFiveMatches;
return team && team.matches ?
lastFiveMatches = Object.values(teams.find(t => t.name === team.name).matches).sort(compare).reverse().slice(0, 5).map((match) => {
if(match.winner === team.name){
return 'W ';
}
else if(match.winner !== team.name){
return 'L ';
}
else {
return 'D ';
}
})
:
'---'
}
and now how to use it in your table:
<td className="stats">{form(team, teams)}</td>
make your functions clean and not dependent on specific this or scopes.
You could bind the specific scope, but that is not something you would like to do.
Update:
After reviewing the code, as I thought it was the scope issue
Please add a constructor to the component that contains the 'form' method and inside it
this.form = this.form.bind(this)
Or you can use ES6 instead
On table props:
<Table
teams={teams}
form={team=> this.form(team)}
/>

Render 2 table rows in ReactJS

I want to achieve expandable row functionality for table.
Let's assume we have table with task names and task complexity. When you click on one task the description of task is shown below. I try to do it this way with ReactJS (in render method):
if (selectedTask === task.id) {
return [
<tr>
<td>{task.name}</td>
<td>{task.complexity}</td>
</tr>,
<tr>
<td colSpan="2">{task.description}</td>
</tr>
];
} else {
return <tr>
<td>{task.name}</td>
<td>{task.complexity}</td>
</tr>;
}
And it doesn't work. It says:
A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object
I tried also to wrap 2 rows in a div but I get wrong rendering.
Please, suggest correct solution.
The render() method on a React component must always return a single element. No exceptions.
In your case, I would suggest wrapping everything inside a tbody element. You can have as many of those as you want in a table without disrupting your row structure, and then you'll always return one element inside render().
if (selectedTask === task.id) {
return (
<tbody>
<tr>
<td>{task.name}</td>
<td>{task.complexity}</td>
</tr>,
<tr>
<td colSpan="2">{task.description}</td>
</tr>
</tbody>
);
} else {
return (
<tbody>
<tr>
<td>{task.name}</td>
<td>{task.complexity}</td>
</tr>
</tbody>
);
}

Categories

Resources