in my app.js
in const APP
i am returning
<Display results = {(good,neutral,bad)}></Display>
which are all numbers
in my display component which i have as this
const Display = ({good,neutral,bad}) => (
the parameters becomes undefined, or any. how come the numbers are not being passed.
full code
import { useState } from 'react'
const App = () => {
// save clicks of each button to its own state
const [good, setGood] = useState(0)
const [neutral, setNeutral] = useState(0)
const [bad, setBad] = useState(0)
return (
<div>
<h1>give feedback</h1>
<button onClick={() => setGood(good +1)}>Good </button>
<button onClick={() => setNeutral(neutral +1)}>Neutral</button>
<button onClick={() => setBad(bad +1)}>Bad</button>
<h1>Statistics</h1>
<Display results = {(good,neutral,bad)}></Display>
<h1>{good}{ neutral} {bad}</h1>
</div>
)
}
const Display = ({good,neutral,bad}) => (
console.log(good),
<table>
<tr>
<td>good</td>
<td>{good}</td>
</tr>
<tr>
<td>neutral</td>
<td>{neutral}</td>
</tr>
<tr>
<td>bad</td>
<td>{bad}</td>
</tr>
<tr>
<td>all</td>
<td>{good+neutral+bad}</td>
</tr>
<tr>
<td>average</td>
<td>{(good-bad)/(good+neutral+bad)}</td>
</tr>
<tr>
<td>positive</td>
<td>{(good)/(good+neutral+bad)}</td>
</tr>
</table>
)
export default App
The way you are passing props is wrong.Try this
<Display good={good} neutral={neutral} bad={bad}></Display>
In Display you're not destructuring the results prop, but the entire props of the component. So either change how you use the component to
<Display {...{good, neutral, bad}} />
which is short for
<Display good={good} bad={bad} neutral={neutral} />
OR
change the Display component to destructure results
const Display = ({results}) => {
const {good, neutral, bad} = results;
return (
// ...
)
}
and how you use it to
<Display results={{good, neutral, bad}} />
you can change to <Display results = {{good:good, neutral:neutral, bad:bad}}>
Lastly you can receive the results prop as below:
const Display = ({results}) => (
console.log(results),
<table>
<tr>
<td>good</td>
<td>{results.good}</td>
</tr>
<tr>
<td>neutral</td>
<td>{results.neutral}</td>
</tr>
<tr>
<td>bad</td>
<td>{resuts.bad}</td>
</tr>
<tr>
<td>all</td>
<td>{good+neutral+bad}</td>
</tr>
<tr>
<td>average</td>
<td>{(results.good-results.bad)/(results.good+neutral+results.bad)}</td>
</tr>
<tr>
<td>positive</td>
<td>{(results.good)/(rsults.good+results.neutral+results.bad)}</td>
</tr>
</table>
)
Note: Remember you can not divide 0, you may probably get an error during division compilation
your problem is here
<Display results = {(good,0,0)}></Display>
it should be
<Display results={{good, neutral:0, bad:0}} />
or probably
<Display results={{good, neutral, bad}} />
Related
I have created the table and I have different types of elements that I want to add. After adding the element I want the option to delete one specific element by clicking on the remove button.
import * as React from 'react';
import { useState } from 'react';
import { Table } from 'reactstrap';
import { Button } from 'reactstrap';
export default function App() {
let [myArray, updateMyArray] = useState([]);
function addElement() {
updateMyArray((arr) => [
...arr,
<Element value={myArray.length} handleDelete={handleDelete} />,
]);
}
const handleDelete = (index, e) => {
updateMyArray(myArray.filter((item) => item.value !== e.target.value));
};
return (
<div>
<Button onClick={addElement}>Add Element</Button>
<Table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>{myArray}</tbody>
</Table>
</div>
);
}
function Element({ value, handleDelete }) {
return (
<tr>
<td>{value}</td>
<td>Test</td>
<td>
<Button onClick={(e) => handleDelete(value, e)}>Remove Element</Button>
</td>
</tr>
);
}
With this code snippet, I have an option to create as many elements as I want. But if I create, let's say 10 elements, and I want to delete the 5th element, one cannot delete only that element, but all elements added after the 5th element is created. I am new at the react therefore I cannot realize what causes this problem.
The link for the code: https://stackblitz.com/edit/react-ts-7mwhmw?file=App.tsx
You should create unique index each element of array and dont store component as #Chrisg mentioned.
solution:
let [myArray, updateMyArray] = useState([]);
function addElement(value) {
updateMyArray((arr) => [...arr,value]);
}
const handleDelete = (index) => {
updateMyArray(myArray.filter((item,i) => index !== i));
};
return (
<div>
<Button onClick={() => addElement("newElement")}>Add Element</Button>
<Table>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th></th>
</tr>
</thead>
<tbody>{myArray.map((item,index) => {
return <tr>
<td>{item} {index}</td>
<td>Test</td>
<td>
<Button onClick={() => handleDelete(index, item)}>Remove Element</Button>
</td>
</tr>
})}</tbody>
</Table>
</div>
);
link : https://stackblitz.com/edit/react-ts-wqsmfq?file=App.tsx
I want an app.js that imports a component, that generates a row in a table for each element in an array.
import myRows from './myRows';
const myApp = ({ values}) => {
return (
<div>
<div>
{values.map((entry, index) => {
return <myRows entry={entry} key={index}/>
})}
</div>
</div>
)
}
...
const myRows = ({ entry}) => {
return (
**ROW ENTRY like row name = entry.name**
)
}
...
Maybe I should create in the my App.js a table and create in the map function a row for each entry in values? Idk how to do that.
I want a simple table where each row is created with each entry in values
My idea is not working and mybe it is stupid and there are many better ways..
import myRows from './myRows';
const myApp = ({ values}) => {
return (
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
<th>5</th>
<th>6</th>
<th>7</th>
</tr>
</thead>
<tbody>
{values.map((entry, index) => {
return <myRows entry={entry} key={index}/>
})}
</tbody>
</table>
)
}
...
const myRows = ({ entry}) => {
return (
<tr>
<th>entry.name</th>
<td>entry.secondName</td>
<td>C</td>
<td>D1</td>
<td>entry.value22</td>
<td>E3</td>
<td>E4/</td>
</tr>
)
}
...
Don't use index as key. Each entry should have a unique identifier; either an id or you can interpolate some values to create a unique key for each row (e.g key={${row.name}_${row.createdAt}}
const App = ({ array }) => {
return <table>
<tbody>
{ array.map(row => <Row data={row} key={row.id} />) }
</tbody>
</table>
}
const Row = ({ data }) => {
return <tr>
<td>{data.name}</td>
<td>{data.created}</td>
...
</tr>
}
Data is an array object. I want to render table columns dynamically according to data object. I used this same technique to generate table head its working. Is there any way to fix this issue?
const DataTable = ({data, deleteHandler, loading, tableFields}) => {
const thead = [];
const tbody = [];
const [values, setValues] = useState({});
for (const [key, value] of Object.entries(tableFields)) {
thead.push(<td>{value}</td>);
}
data.map((field) => {
for(const[key,value] of Object.entries(field)){
tbody.push(
<tr>
<td>{value}</td>
</tr>
);
}
})
return (
<Fragment>
<Card className={classes.__bk_admin_card}>
<Table borderless hover className={classes.__bk_admin_table}>
<thead>
<tr>
{thead}
</tr>
</thead>
<tbody>
{tbody}
</tbody>
</Table>
</Card>
</Fragment>
)
}
I am trying to filter through an array so that when a certain tab is clicked, only those results show. I have managed to isolate the certain variables I want to remain but the others that don't fit the criteria still remain. How do I get the filter method to actually render on the page so that the results can be shown. I have searched for hours for and have tried to get the tbody and sort through that but I just get confused as I am mostly new to javascript and react. Can someone point me in the right direction?
Filter Method
const tbody = document.getElementsByTagName('tbody')
console.log(tbody)
//change active class
function addTabBackground() {
const tabs = document.querySelectorAll('[data-tab]')
window.onload = function () {
tabs.forEach(tab => {
tab.addEventListener('click', () => {
if (tab.getAttribute('data-tab') === 'gains') {
listOfOptions.map(option => {
console.log(option.totalProfit)
})
}
tabs.forEach(tab => {
tab.classList.remove('active')
})
tab.classList.add('active')
})
})
}
}
<div className="outputs" >
<table>
<thead>
<tr>
<th>Date</th>
<th>Stock Name</th>
<th>Price Of Option</th>
<th>Number Of Options</th>
<th>Total Amount Spent</th>
<th>Option Sold At</th>
<th>Amount Of Options Sold</th>
<th>Proft</th>
</tr>
</thead>
{listOfOptions.map(option => {
return (
<tbody>
<tr>
<td>{option.clock}</td>
<td>{option.name.toUpperCase()}</td>
<td>${option.price}</td>
<td>{option.amountOfOptions}</td>
<td>${option.totalAmountSpent.toFixed(2)}</td>
<td>${option.optionPriceSoldAt}</td>
<td>{option.amountOfOptionsSold}</td>
<td style={{ color: option.totalProfit >= 0 ? 'green' : 'red' }}>${option.totalProfit.toFixed(2)}</td>
</tr>
</tbody>
)
})}
</table>
</div>
I have used React-Bootstrap-v5 to get Nav, Nav.Item with eventKey and then passed selectedKey in its onSelect function to change the tabs.
Then once we get the data inside my data variable, I used the map function to go over the array. Inside Map Function I have used the required condition to filter the elements i.e. variable = 'Open' or 'Live'.
This will only show the Open type in Open Tab and Live Type Data inside Live Tab.
Hope it's clear to you.
import React, { useEffect, useState } from 'react';
const TestSeries = () => {
// Declare Variable for data to be fetched from API
const [data, setData] = useState([]);
const fetchTestData = async () => {
const response = await axios.get(site_ip + '/apiLink');
setData(response.data.Content);
};
useEffect(() => {
fetchTestData();
}, []);
// State Variable to keep track of active tab
const [activeTab, setActiveTab] = useState('Open');
return (
<>
<Nav
activeKey={activeTab}
fill
variant="pills"
onSelect={(selectedKey) => {
setActiveTab(selectedKey);
}}
>
<Nav.Item>
<Nav.Link eventKey="Open">Open</Nav.Link>
</Nav.Item>
<Nav.Item>
<Nav.Link eventKey="Live">Live</Nav.Link>
</Nav.Item>
</Nav>
<br />
<Table striped bordered hover>
<thead>
<tr>
<th>#</th>
<th>Column1</th>
<th>Column2</th
<th>Column3</th>
<th>Column4</th>
<th>Data Type</th>
</tr>
</thead>
<tbody>
{data.map((item, index) =>
// Condition by which data will be filtered
item.data_type == activeTab ? (
<tr>
<td>{index + 1}</td>
<td>{item.col1}</td>
<td>{item.col2}</td>
<td>{item.col3} </td>
<td>{item.col4}</td>
<td>{item.data_type}</td>
</tr>
) : null
)}
</tbody>
</Table>
</>
);
};
export default TestSeries;
Result
Assuming from the comment that you have something vaguely looking like:
function Page() {
return (
<>
<Navbar />
<Table />
</>
)
}
What you need to do is to store the current tab in a state, and pass this state down to the Table component so that you can use a Array.filter when rendering your table.
function Page() {
const [activeTab, setActiveTab] = useState(DEFAULT_ACTIVE_TAB)
return (
<>
<Navbar activeTab={activeTab} setActiveTab={setActiveTab} />
<Table activeTab={activeTab} />
</>
)
}
Your Navbar component should have a onClick handler where it is calling the setActiveTab function when the active tab change.
Then in your Table component you should have something like this:
function Table({ activeTab }) {
return (
<table>
...
{listOfOptions
.filter(option => /* something depending on the activeTab */)
.map(option => <... />)
}
</table>
}
Im sending in an array via props to a component, but i cant use map on the array. It says that
.map is not a function
My code:
const AuthorList = (authors) => {
return(
<table className="table">
<thead>
<tr>Firstname</tr>
<tr>Lastname</tr>
</thead>
<tbody>
{authors.map(author =>
<AuthorListRow key={author.id} author={author} />
)}
</tbody>
</table>
);
};
This is what the Chrome React dev tool looks like:
Issue is, whenever you pass any data from parent to child, it get passed through props, and you need to receive the props in child component and access the specific values, write it like this:
const AuthorList = (props) => {
return(
<table className="table">
<thead>
<tr>Firstname</tr>
<tr>Lastname</tr>
</thead>
<tbody>
{props.authors.map(author =>
<AuthorListRow key={author.id} author={author} />
)}
</tbody>
</table>
);
};
or
const AuthorList = ({authors}) => {
return(
<table className="table">
<thead>
<tr>Firstname</tr>
<tr>Lastname</tr>
</thead>
<tbody>
{authors.map(author =>
<AuthorListRow key={author.id} author={author} />
)}
</tbody>
</table>
);
};
Reason why 2nd one is working: because props is an object, when you write {authors} it means you are receiving only authors value from object props. In that case you don't need to write props.authors.
Check this example:
obj = {a:1,b:2,c:3}
let {a} = obj;
console.log(a);
Props will be passed in as an object, so right now authors is acting as an alias for props. Accessing the authors property on props should work as long as that prop is being declared with an array.
const AuthorList = (props) => {
return(
// ..
{props.authors.map(author =>
<AuthorListRow key={author.id} author={author} />
)}
// ..
);
};