How to access values in Reactjs - reactjs

I am trying to access the values stored in a list in my react component. When looped through, all data can be accessed but cannot be accessed by the syntax { variable.data_key }
code: https://pastebin.com/wS5SL22n
line 9: I initialized a list of data
line 36: I started looping through the list of data.
line 38: I created a table and tried to access items from the data list.
line 55: take the table as state
line 79: displaying the contents
import React, { Component } from "react";
import "./App.css";
class App extends Component {
constructor(props) {
super(props);
/* DATABASE */
const movies = [
{
id: 0,
src:
"https://image.tmdb.org/t/p/w185_and_h278_bestv2/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg",
title: "movie one",
overview: "overview one"
}
];
let movieRows = [];
/* LOOPING THROUGH DATABASE */
movies.forEach(item => {
/* MAKING AN ELEMENT */
const moveDataTable = (
<table key={movies.id}>
<tbody>
<tr>
<td>
<img alt="poster" width="80" src={movies.src} />
</td>
<td>{movies.title}</td>
</tr>
</tbody>
</table>
);
/* PUSING DATA TO THE LIST */
movieRows.push(moveDataTable);
console.log(movieRows);
});
this.state = { rows: movieRows };
}
render() {
return (
<div className="App">
<p> {this.state.rows} </p>
</div>
);
}
}
export default App;

You have accepted an answer but still, I want to provide a different logic.
The main problem here you are trying to reach the wrong item. You are trying with movies but in your forEach loop it is item. Though, I don't recommend using forEach like that then set the state. At some point, there might be some glitches. Use map for such situations. Also, do not use your constructor like defining your functions.
const movies = [
{
id: 0,
src:
"https://image.tmdb.org/t/p/w185_and_h278_bestv2/7WsyChQLEftFiDOVTGkv3hFpyyt.jpg",
title: "movie one",
overview: "overview one"
},
{
id: 1,
title: "moview two",
overview: "something"
}
];
class App extends React.Component {
state = { movies: [] };
componentDidMount() {
this.setState( {movies} );
}
createTable = () => (
<table key={movies.id}>
<tbody>
{
movies.map( movie =>
<tr>
<td>
<img alt="poster" width="80" src={movie.src} />
</td>
<td>{movie.title}</td>
<td>{movie.overview}</td>
</tr>
)
}
</tbody>
</table>
);
render() {
return (
<div className="App">
{this.createTable()}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

movies is an array, not an object.
movies.forEach(item => ...) means for each item in the movies array. The individual item in the array is item, not movies. You are trying to display movies.src and movies.title. There is no src or title property on the movies array. These properties are on the item in the array. You should be using item.src and item.title.

Instead of accessing movie.id i needed to access item.id as i named the variable as item in the foreach loop.

Related

sort items in state alphabetically

I have a class based React component that is using items in state and rendering result. Here is short snippet how I do this:
class Menu extends Component {
constructor(props) {
super(props);
this.state = {
items: props.items.edges,
someItems: props.items.edges,
}
}
render() {
if (this.state.items.length > 0) {
return (
<div className="container">
<div className="row">
{this.state.someItems.map(({ node }) => {
return (
<div key={node.id}>
<div>
render some data
</div>
</div>
)
})}
</div>
</div>
);
}
}
}
The data is received as objects inside an array, like this:
My question is would it be possible to sort these items alphabetically before being rendered? What would be the best approach for this?
The best approach is to sort the items before you set them to the state. You can use the built in Array.prototype.sort method in order to sort the items. You can use the String.prototype.localeCompare in order to compare strings alphabetically.
I don't know the expected structure of your data so here is a general solution.
class App extends React.Component {
constructor(props) {
super(props);
// Make a copy so as not to modify the original array directly
const sortedCopy = [...props.items];
sortedCopy.sort((a, b) => a.name.localeCompare(b.name));
this.state = {
items: sortedCopy,
};
}
render() {
return (
<div>
{this.state.items.map((item) => (
<p key={item.id}>
<div>Item - {item.name}</div>
</p>
))}
</div>
);
}
}
// Example items prop is out of order
const items = [
{ id: 0, name: "C" },
{ id: 1, name: "B" },
{ id: 2, name: "A" },
{ id: 3, name: "D" },
];
ReactDOM.render(<App items={items} />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Rendering array inside object to a table using react

I'm new in React and I stuck with this.
Suppose I have a state like this
state = {
dataSource: {
model: ["Slip on", "Running", "Sneaker"],
colors: ["Dark", "Light", "Colorful"],
activity: ["School", "Hang out", "Rest"],
}
};
I want to render a table with the header as the name of the object inside dataSource and value correspond to that object.
I already tried using map() and cause I knew that map() can not be used on object I tried to change the state like this
state = {
dataSource: [
["Slip on", "Running", "Sneaker"],
["Dark", "Light", "Colorful"],
["School", "Hang out", "Rest"],
]
};
then try to solve it like this
render() {
<table>
<tbody>
{this.state.dataSource.map((c) => (
<tr>
{c.map((x) => (
<td>{x}</td>
))}
</tr>
))}
</tbody>
</table>
}
it did render the value but not the right way, so I wonder if there is a way to do it? Thanks for your help :)
Object.keys might help
const { Component } = React;
class App extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: {
model: ["Slip on", "Running", "Sneaker"],
colors: ["Dark", "Light", "Colorful"],
activity: ["School", "Hang out", "Rest"],
}
};
}
render() {
const { dataSource } = this.state;
const arr = Array(dataSource.model.length).fill(0);
return <table>
<thead>
<tr>
{Object.keys(dataSource).map(pr => <th key={pr}>{pr}</th>)}
</tr>
</thead>
<tbody>
{arr.map((pr, index) => <tr key={index}>
{Object.keys(dataSource).map(key => <td key={key}>{dataSource[key][index]}</td>)}
</tr>)}
</tbody>
</table>
}
}
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone#6/babel.min.js"></script>
<div id="root"></div>
Map can not work. In case of objects you should use objects methods, for example something like
return
Object.entries(state.dataSource).map(([key: tableName, value]) =>
<div>
<h1>{tableName}</h1>
{value.map(v => <div>{v}</div>}
</div>
)

Component output by pressing the ReactJS button using the props

I have 2 buttons, when I click on one of them, the component will be displayed in tr className = "info". The code is made so that it is universal, if there are 50 different components, then there will be 50 different buttons. And the active button will change the class. I'm trying to do it now with the help of a props, I'm just learning, tell me, please, where is the mistake?
import React, { Component } from 'react';
import './App.css';
import Donald from '/.Donald';
import John from '/.John';
const Counter =({buttonType,id})=>{
const {
buttonType,
children,
} = props;
return (
<div
className = {`${buttonType}`}
onClick={id}
>
{children}
</div>
);
}
Counter.defaultProps={
className = 'notActive'
}
class MyName extends Component {
state = {
array:[
{id:1,component:<Donald/>, name:"My name Donald"},
{id:2,component:<John/>, name:"My name John"},
],
};
render() {
const selectedElement = this.state.array.find(item => item.id === this.state.currComponentId);
return(
<table>
<tbody>
<tr className="trButton">
{
this.state.array.map( (element) => {
return (
<Counter>
<td
className={'active'}
onClick={ () => this.element.id}
>{element.name}
</td>
</Counter>
)
})
}
</tr>
<tr className="info">
{selectedElement.component}
</tr>
</tbody>
</table>
)
}
}
export default MyName;
I see couple of issues with the code
(1) Firstly, I think you are using incorrect path for import these components i.e. Use ./Donald instead of /.Donald (notice the . before / not after), similarly './John'.
(2) Secondly you're not setting initial value for currComponentId in state. Lets set that too
state = {
array:[
{id: 1, component: <Donald/>, name:"My name Donald"},
{id: 2, component: <John/>, name:"My name John"},
],
currComponentId: 1
};
(3) Also I think you are trying to change the currComponentId in onClick. So it will be
<Counter>
<td
className={'active'}
onClick={ () => this.setState({currComponentId: element.id})}
>
{element.name}
</td>
</Counter>

reactjs - How to render a component which render return a component?

for the following example I have a component GetCurrentVisitor which renders Visitors.
However it will only render the <h1> tag and the table is empty. I suspect I need to use ReactDOM to render Vistors component as well. But how to do it?
var VISITORS = [
{
first_name: 'Harry',
last_name: 'Potter'
},
{
first_name: 'Hermione',
last_name: 'Granger'
}
]
class GetCurrentVisitors extends React.Component {
constructor(props) {
super(props);
this.state = {
visitors: VISITORS
}
}
render () {
return (
<div>
<h1>Current visitors</h1>
<Visitors visitors={this.state.visitors} />
</div>
);
}
}
class Visitors extends React.Component {
constructor(props) {
super(props);
}
render () {
return (
<table>
{this.props.visitors.forEach(
function(visitor) {
<tr>
<td>
{console.log('from: ', visitor.first_name)}
{visitor.first_name}
</td>
</tr>
})}
</table>
);
}
}
ReactDOM.render(
<GetCurrentVisitors />, document.getElementById('getcurrentvisitors'))
In this case you should use .map instead of .forEach
{this.props.visitors.map(function(visitor, index) {
return <tr key={index}>
<td>{ visitor.first_name } </td>
</tr>
})}
Example
You can also are able to use .forEach but in another way fiddle
render () {
let itemList = [];
this.props.visitors.forEach(function(visitor,index) {
itemList.push(<tr key={index}><td>
{visitor.first_name}
</td></tr>
)
})
return (
<table>
{itemList}
</table>
);
}
As for me Array.prototype.map more easy to use with React. It just another example.
Thanks

React - mapping data to rows that are formed during a map function

I have a component called Cells which renders with data that is gotten from a flux store. My problem is that I want to render this data to a specific row but because of the way I am rendering the rows (they are dynamic so you can add them to the table), I am struggling to give the rows identifiers which the cell component can render into. I hope that makes sense!
Here is the code:
Cells Component:
import React from 'react';
export default class Cells extends React.Component {
render() {
return (
<td>{this.props.value}</td>
);
}
}
Table Component:
import React from 'react';
import TableHeader from './TableHeader.jsx';
import Cells from './Cells.jsx';
import RowForm from './RowForm.jsx';
import {createRow} from '../../actions/DALIActions';
import AppStore from '../../stores/AppStore';
export default class Table extends React.Component {
state = {rows: [], cellValues: [], isNew: false, isEditing: false};
updateState = () => this.setState({cellValues: AppStore.getCellValues()});
componentWillMount() {
AppStore.addChangeListener(this.updateState);
}
handleAddRowClickEvent = () => {
let rows = this.state.rows;
rows.push({isNew: true});
this.setState({rows: rows});
};
handleEdit = (row) => {
this.setState({isEditing: true});
};
editStop = () => {
this.setState({isEditing: false});
};
handleSubmit = (access_token, id, dataEntriesArray) => {
createRow(access_token, id, dataEntriesArray);
};
componentWillUnmount() {
AppStore.removeChangeListener(this.updateState);
}
render() {
let {rows, cellValues, isNew, isEditing} = this.state;
let headerArray = AppStore.getTable().columns;
let cells = this.state.cellValues.map((value, index) => {
return (
<Cells key={index} value={value.contents} />
);
});
return (
<div>
<div className="row" id="table-row">
<table className="table table-striped">
<thead>
<TableHeader />
</thead>
<tbody>
//////////// This is where the render of the data would happen/////////////
{rows.map((row, index) => this.state.isEditing ?
<RowForm formKey={index} key={index} editStop={this.editStop} handleSubmit={this.handleSubmit} /> :
<tr key={index}>
{this.state.cellValues ? cells : null}
<td>
<button className="btn btn-primary" onClick={this.handleEdit.bind(this, row)}><i className="fa fa-pencil"></i>Edit</button>
</td>
</tr>
)}
///////////////End/////////////////
</tbody>
</table>
</div>
<div className="row">
<div className="col-xs-12 de-button">
<button type="button" className="btn btn-success" onClick={this.handleAddRowClickEvent}>Add Row</button>
</div>
</div>
</div>
);
}
}
I know this isn't probably the best way to achieve what I want (any tips on that would be appreciated as well), but its what I have to work with at the moment!
Any help would be much appreciated, especially examples!
Thanks for you time!
Instead of having one object (rows) that contains row headers, and another object that contains all cells for all rows (cellvalues), I would advise you to put the cell data inside the individual row data in some way, so that your data structure would look something like this:
rows = [
{ rowID: 100, cells: [
{ cellID: 101, value: 'data' },
{ cellID: 102, value: 'data' }
]
},
{ rowID: 200, cells: [
{ cellID: 201, value: 'data' },
{ cellID: 202, value: 'data' }
]
}
]
That way, you pass the cellValues per row, and that allows you to have different cells per row.
Make a separate component for <Row>, which renders:
return
<tr>
{this.props.cells.map( cell => {
return <Cell key={cell.cellID} value={cell.value} />
})}
</tr>
And change the <tr> bit inside your main render to:
<Row key={row.keyID} cells={row.cells}/>
Finally: it is a bad idea to use the index for keys, as in key={i}. Use a key that uniquely identifies the content of the cell/ row.
UPDATE: A typical situation is that cells or rows are first created in front-end, and only get their database ID after posting to database.
Options to still get unique IDs for the keys are:
upon creation of the cell or row in react, give the cell/row a unique ID in the form of a timestamp. After getting back the response from the database, replace the timestamp with the official database key. (this is when you do optimistic updates: show new rows temporarily, until the database gives you the official rows).
do not display the row/cell, until you get response back from server with official IDs
create a unique key by hashing the content of all cell/row contents (if you are pretty sure that cell/row contents are not likely to be identical)
Hope this helps.
You need to pass row to cells render method :
{rows.map((row, index) => this.state.isEditing ?
<RowForm formKey={index} key={index} editStop={this.editStop} handleSubmit={this.handleSubmit} /> :
<tr key={index}>
{(row.cellValues || []).map((value, index) => {
return (
<Cells key={index} value={value.contents} />
)})
}
<td>
<button className="btn btn-primary" onClick={this.handleEdit.bind(this, row)}><i className="fa fa-pencil"></i>Edit</button>
</td>
</tr>
)}
Hope this help!

Resources