View not re-rendered even when JSX has changed - reactjs

function App()
{
const [rows_data, SET_rows_data] = useState([]);
useEffect(() => {
get_rows_data(SET_rows_data); //Fetches the data. Runs only once
}, []);
useEffect(() => {
console.log(rows_data); //This rightly trigggers twice, and shows an empty array and the full array once fetched
}, [rows_data]);
return (
<div>
{Table_Renderer(rows_data)}
</div>
); //Doesn't re-render when rows_data changes
}
function get_rows_data(SET_rows_data)
{
fetch(...)
.then((res) => res.json())
.then((data) => {
SET_rows_data(data["rows"]); //Required data is within the "rows" object
});
}
function Table_Renderer(rows_data)
{
return (
<table>
<thead>
...
</thead>
<tbody >
{rows_data.map(row => {
return (
<tr>
...
</tr>
)
})}
</tbody>
</table>
)
}
export default (App);
I've added comments above to explain the issue.
The console.log in the useEffect, triggers twice as expected. But the 2nd render doesn't happen, even though the data in the JSX has changed.
If I re-save my work while 'npm start' is running, the data is properly displayed though

Hi #Dalhousie,
As you describe above, The Table_Renderer component is not re-rendering when the rows_data state changes. Its obvious behavior
Because Table_Renderer component does not have access to the rows_data state, and so it is not aware that the state has changed.
function App() {
const [rows_data, SET_rows_data] = useState([]);
useEffect(() => {
get_rows_data(SET_rows_data); // Fetches the data. Runs only once
}, []);
return (
<div>
<Table_Renderer rowsData={rows_data} />
</div>
);
}
function Table_Renderer({ rowsData }) {
return (
<table>
<thead>
...
</thead>
<tbody>
{rowsData.map(row => {
return (
<tr>
...
</tr>
);
})}
</tbody>
</table>
);
}

Related

Rendering a Table Axios ReactJS

i'm trying to render all booked slots using a table, i suspect the problem is with the Axios call since i get "Cannot GET /api/get/week1" but i'm not sure how to test this theory or how check if the array actually contains any values, any help would be greatly appreciated!
function BookingTable() {
useEffect(() => {
Axios.get('http://localhost:3001/api/get/week1').then((response) => {
setIsBooked(response.data)
console.log(response.data);
})
}, []);
const [isBooked, setIsBooked] = useState([])
const renderTableData = () => {
return isBooked.map((val) => (
<tr class>
<td>{val.booked}</td>
</tr>))
}
return (
<table id="table">
<thead>
<tr>
<th>Booked</th>
</tr>
</thead>
<tbody>
{renderTableData}
</tbody>
</table>
)
}
export default BookingTable
you call function incorrectly call it like renderTableData() working demo link
import axios from "axios";
import { useEffect, useState } from "react";
import "./styles.css";
function BookingTable() {
const [isBooked, setIsBooked] = useState([]);
useEffect(() => {
axios.get("https://jsonplaceholder.typicode.com/posts").then((response) => {
setIsBooked(response.data);
});
}, []);
const renderTableData = () => {
return isBooked?.map((val) => (
<tr class>
<td>{val.id}</td>
</tr>
));
};
return (
<table id="table">
<thead>
<tr>
<th>Booked</th>
</tr>
</thead>
<tbody>{renderTableData()}</tbody>
</table>
);
}
export default BookingTable;

how to fix problem on No data available in table in data table react js

I'm new in react js and I want to display all data from database into data table but I'm getting an error of No data available in table. I also added the getStudent to the useEffect so that it would run continuously
this is my useState and useEffect snippet code:
const [student, setStudent] = useState([]);
const getStudent = async () => {
try {
const response = await fetch("http://localhost:5000/admin/get_allstudent");
const data = await response.json();
setStudent(data);
} catch (err) {
console.error(err.message);
}
};
const dataTable = () => {
$(document).ready(function () {
$("#example").DataTable();
});
};
useEffect(() => {
setInterval(dataTable, 1000);
getStudent();
}, []);
and this is my render:
<table id="example" className="display ">
<thead>
<tr>
<th>Name</th>
<th>Username</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{student.map((item, index) => {
return (
<tr key={item.stu_id}>
<td>{item.stu_name}</td>
<td>{item.stu_username}</td>
<td>
<Edit item={item} />
<button className="btn btn-danger" onClick={()=> deleteStudent(item.stu_id)}
>
Delete
</button>
</td>
</tr>
);
})}
</tbody>
</table>;
And this is the output
i don't know about jQuery part of your code and i don't think that is necessary
first try to remove that part and then check if student has value or not
you can check the student value by using useEffect
useEffect(() => {
if (student) console.log('data is ok ' , student)
}, [student]);
if the message showed up in console and it was not empty
then there should be no problem

Acessing specific table data from table row in React

It is my first time fetching data from an API and I'm quite new to React. Would be greatly appreciated if someone could help!
I am having trouble accessing some data inside a table row. I am trying to access the name property by clicking the row. What I want is to copy the name property from clicking the specific row.
Also, my useEffect keeps fetching data non-stop. I've tried to change the dependencies but it keeps doing it no matter what I do. I am passing the endpoint to the API from the button click.
Another thing is that when I am getting the data I would like to access every index of the array members but I tried and couldn't figure it out. So I am only accessing the index[1] (resp.guild.members[1].characters).
My Code:
import React, { useState, useEffect } from "react";
const Tabledata = ({ guildName }) => {
const [members, setMembers] = useState([]);
const [membersOnline, setMembersOnline] = useState([]);
useEffect(() => {
fetch(`https://api.tibiadata.com/v2/guild/${guildName}.json`)
.then((res) => res.json())
.then((resp) => {
console.log(resp);
setMembers(resp.guild.members[1].characters);
setMembersOnline(() =>
members.filter((player) => player.status !== "offline")
);
})
.catch((err) => console.log(err));
}, [members, guildName]);
return (
<div className="container">
<h1>Enemies Online</h1>
<table className="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Level</th>
<th>Vocation</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{membersOnline.map((d, id) => (
<tr
key={d.id}
onClick={(e) => {
console.log(this.d.name);
navigator.clipboard.writeText(`exiva "${e.target.value}`);
}}
>
<td>{d.name}</td>
<td>{d.level}</td>
<td>{d.vocation}</td>
<td>{d.status}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Tabledata;
Code working:
import React, { useState, useEffect } from "react";
const Tabledata = ({ guildName }) => {
// const [members, setMembers] = useState([]);
const [membersOnline, setMembersOnline] = useState([]);
const [header, setHeader] = useState("");
useEffect(() => {
fetch(`https://api.tibiadata.com/v2/guild/${guildName}.json`)
.then((res) => res.json())
.then((resp) => {
const members = resp.guild;
setHeader(resp.guild.data.name);
const allCharacters = members.reduce((accum, iter) => {
accum.push(...iter.characters);
return accum;
}, []);
console.log(members);
console.log(allCharacters);
setMembersOnline(() =>
allCharacters.filter((player) => player.status !== "offline")
);
})
.catch((err) => console.log(err));
}, [guildName]);
return (
<div className="container">
<h1>{header}</h1>
<table className="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Level</th>
<th>Vocation</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{membersOnline.map((d) => (
<tr
key={d.id}
onClick={(e) => {
navigator.clipboard.writeText(
`exiva "${e.currentTarget.children[0].innerText}`
);
}}
>
<td>{d.name}</td>
<td>{d.level}</td>
<td>{d.vocation}</td>
<td>{d.status}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Tabledata;
However, if I try to assign resp.guild to members somehow reduce won't work..something like this:
import React, { useState, useEffect } from "react";
const Tabledata = ({ guildName }) => {
const [members, setMembers] = useState([]);
const [membersOnline, setMembersOnline] = useState([]);
useEffect(() => {
fetch(`https://api.tibiadata.com/v2/guild/${guildName}.json`)
.then((res) => res.json())
.then((resp) => {
setMembers(resp.guild);
setHeader(resp.guild.data.name);
const allCharacters = members.reduce((accum, iter) => {
accum.push(...iter.characters);
return accum;
}, []);
setMembersOnline(() =>
allCharacters.filter((player) => player.status !== "offline")
);
})
.catch((err) => console.log(err));
}, [members, guildName]);
return (
<div className="container">
<h1>Enemies Online</h1>
<table className="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Level</th>
<th>Vocation</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{membersOnline.map((d, id) => (
<tr
key={d.id}
onClick={(e) => {
console.log(this.d.name);
navigator.clipboard.writeText(
`exiva "${e.target.value.innerText}`
);
}}
>
<td>{d.name}</td>
<td>{d.level}</td>
<td>{d.vocation}</td>
<td>{d.status}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Tabledata;
It will throw an exception at reduce saying it is not a function
I have refactored your code, and it is working in a code sandbox here with no errors in rendering.
I made a few changes after looking at your updated question and looking at the API that you are using.
I removed members as a state object
I am setting the key value of the map function to the index of the array, because id is not a property of the members in the JSON response body.
I removed members from the dependency array as it no longer a managed state
I removed setHeader because it is not defined anywhere in your code example
I changed the filter to return offline members because there were literally no members online at the time of writing this.
Please reference the code sandbox I linked in order to fully understand any issues you come across implementing my code.
As a note: navigator.clipboard.writeText() as you have written it does not work in the code sandbox, but a console.log will show the value that is being written to the clipboard is correct. Questions about clipboard should be asked in their own stack overflow post.
const Tabledata = ({ guildName }) => {
const [membersOnline, setMembersOnline] = useState([]);
useEffect(() => {
fetch(`https://api.tibiadata.com/v2/guild/${guildName}.json`)
.then((res) => res.json())
.then((resp) => {
const { members } = resp.guild;
const allCharacters = members.reduce((accum, iter) => {
accum.push(...iter.characters);
return accum;
}, []);
setMembersOnline(
allCharacters.filter(({ status }) => status === "offline")
);
})
.catch((err) => console.log(err));
}, [guildName]);
return (
<div className="container">
<h1>Enemies Online</h1>
<table className="table table-bordered">
<thead>
<tr>
<th>Name</th>
<th>Level</th>
<th>Vocation</th>
<th>Status</th>
</tr>
</thead>
<tbody>
{membersOnline.map((d, i) => (
<tr
key={i}
onClick={(e) => {
navigator.clipboard.writeText(
`exiva ${e.currentTarget.children[0].innerText}`
);
}}
>
<td>{d.name}</td>
<td>{d.level}</td>
<td>{d.vocation}</td>
<td>{d.status}</td>
</tr>
))}
</tbody>
</table>
</div>
);
};
export default Tabledata

React toggle for sorting doesn't work. Individual functions work

I created two buttons for sorting the year field of a list ascending and descending. They work perfectly. And then I want to replace the buttons with one toggle button to change between ascending and descending. It doesn't work. My codes below. Would someone please advise? Thank you very much.
import { useEffect, useState } from 'react';
import {Button} from "reactstrap";
const MovieList = () => {
const [movies, setMovies] = useState([])
const [sort, setSort] = useState(true)
// Sort by Year
// I need to use localeCompare because the year is string
const sortByYearDesc = () => {
const sorted = [...movies].sort((a, b) => {
return b.year.localeCompare(a.year);
});
setMovies(sorted);
}
const sortByYearAsc = () => {
const sorted = [...movies].sort((a, b) => {
return a.year.localeCompare(b.year);
});
setMovies(sorted);
}
const toggleSort = () => {
setSort(!sort)
return sort ? sortByYearAsc : sortByYearDesc
}
return (
<div className="container">
<h1>Movies</h1>
<hr />
<div>
<Button onClick={toggleSort} color="info">{sort ? "Sort by Desc" : "Sort by Asc"}</Button>
</div>
<div>
<table className="table table-bordered table-striped">
<thead className="thead-dark">
<tr>
<th>Year</th>
<th>Film Name</th>
<th>Oscar Winner</th>
<th>Country</th>
</tr>
</thead>
<tbody>
{movies.map(movie => (
<tr key={movie.id}>
<td>{movie.year}</td>
<td>{movie.filmName}</td>
<td>{movie.winner}</td>
<td>{movie.country}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
)
}
export default MovieList;
Since sortByYearAsc and sortByYearDesc are functions, you need to execute them in the toggleSort function.
e.g. the updated code will be
const toggleSort = () => {
setSort(prevSort => !prevSort)
!sort ? sortByYearAsc() : sortByYearDesc() // since the state is not updated yet.
}
Option 2
You can also use the useEffect hook, whenever the sort updates, that useEffect will execute the relevant function.
Only update the state in toggleSort
const toggleSort = () => {
setSort(prevSort => !prevSort)
}
then use the useEffect based on the sort changes
useEffect(() => {
sort ? sortByYearAsc() : sortByYearDesc()
}, [sort])

searchfilter with using react hook(useEffect / useState)

I am trying to create a searchBar.
When I type some value on input, I would like my listitems from github api to be re-listed with the value on searchBar.
import './App.css';
function App() {
const [datas, setDatas] = useState([]);
const [userid, setUserid] = useState('');
const inputChanged = (event) => {
setUserid(event.target.value)
}
const searchBar = () => {
}
useEffect(() => {
fetch('https://api.github.com/search/repositories?q=react')
.then(response => response.json())
.then(data => {
setDatas(data.items)
})
},[])
return (
<div className="App">
<h1>Repositories</h1>
<input id="searchInput"type="text" placeholder="search" name="search" value={userid} onChange={inputChanged}/>
<button onClick={searchBar}>Search</button>
<table>
<tbody>
<tr>
<th>Name</th>
<th>URL</th>
</tr>
{
datas.map((data, index) =>
<tr key={index}>
<td>{data.full_name}</td>
<td><a href={data.html_url}>{data.html_url}</a></td>
</tr>
)
}
</tbody>
</table>
</div>
);
}
export default App;
Here is my code and the image of the localhost
useEffect has an array at the end, when left empty what's in useEffect only update once. You can add variables to that array, to update when that variable changes.
Here you need to write: useEffect(your function,[userid]);

Resources