In React (Next.js), I'm trying to make a click event in a custom hook change the state of parent component which would then display a list below the data table, but am unable to get it because the API call and data variable are in the parent component while the click event is in the custom hook child. I've tried putting all logic from each within either file, but to no avail. Any advice appreciated!
Component Next.js page:
import React, { useState } from "react";
import Routes from "../components/Routes";
import Table from "../components/useTable";
export const getStaticProps = async () => {
const res = await fetch(
"https://example.com/api/v4/...."
);
const data = await res.json();
return {
props: { data },
};
};
const Industries = ({ data }) => {
// Get companies, remove duplicates and sort
const companyId = data.map((o) => o.name);
const companies = data
.filter(({ name }, index) => !companyId.includes(name, index 1))
.sort((a, b) => a.name.localeCompare(b.name));
// Industry button click state
const [industrySelected, setIndustrySelected] = useState("");
// Get number of companies per industry
const counted = companies.reduce((obj, v) => {
obj[v.industryTitle] = (obj[v.industryTitle] || 0) 1;
return obj;
}, {});
// Convert object to array
const array = Object.entries(counted);
// Sort by descending order
const sorted = array.sort((a, b) => b[1] - a[1]);
return (
<div>
<Routes />
<Table data={array} />
<h2>
<a id="list"></a>
{industrySelected}
</h2>
<ol>
{companies
.filter((item) => item.industryTitle === industrySelected)
.map((item) => (
<li key={item.symbol}>
{item.name} <u>({item.symbol})</u>
</li>
))}
</ol>
</div>
);
};
export default Industries;
Custom hook useTable.js:
import React, { useState } from "react";
...
const Table = (props) => {
const { items, requestSort, sortConfig } = useSortableData(props.data);
// Industry button click state
const [industrySelected, setIndustrySelected] = useState("");
const getClassNamesFor = (name) => {
if (!sortConfig) {
return;
}
return sortConfig.key === name ? sortConfig.direction : undefined;
};
return (
<div>
<table>
<thead>
...
</thead>
<tbody>
{items.map((item) => (
<tr key={item[0]}>
<td>
<a
href="#list"
onClick={() => {
setIndustrySelected(item[0]);
}}
>
{item[0]}
</a>
</td>
<td>{item[1]}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Table;
CodePudding user response:
Move const [industrySelected, setIndustrySelected] = useState("");
to the Industries component and pass down the setIndustrySelected
function as a prop to Table as onIndustrySelected
and call it in the onClick instead of setIndustrySelected(item[0]);
CodePudding user response:
you need to lift "up the state".
by having useState inside , when using setIndustrySelected() tou are changing only the scope of the function itself.
You need to pass setIndustrySelected as a prop instead
<Table data={array} setIndustrySelected={setIndustrySelected} />