Getting a console error called "data.map" is not a function - html

I am trying to build a table based of an Axios get call. And when I'm trying to create the rows for my table, I'm getting an error called "data.map is not a function".
Here's my Dashboard main function:
import axios from "axios"
import { useEffect, useState } from 'react';
import Navbar from "../components/tenantComponents/NavBar"
import Table from '../components/tenantComponents/Table'
export default function OwnerDashboard2(){
const [ownerData, setTenantData] = useState([])
const [dataTable, setDataTable] = useState([]);
useEffect(() => {
axios.get('https://t00axvabvb.execute-api.us-west-1.amazonaws.com/dev/propertiesOwner?owner_id=100-000003')
.then(res => setDataTable(res.data))
console.log(dataTable);
axios.get('https://t00axvabvb.execute-api.us-west-1.amazonaws.com/dev/propertiesOwner?owner_id=100-000003')
.then(res => setTenantData(res.data))
.catch(err => console.log(err))
});
const column = [
{ heading: 'Addresses', value:'result.address'},
{ heading: 'Property Type', value:'result.property_type'},
{ heading: 'Rent', value:'result.listed_rent'},
]
return(
<div className="OwnerDashboard2">
<div>
{ownerData.length !== 0 && <h3 style={{paddingLeft: "7rem", paddingTop:"2rem"}}>{ownerData.result[0].owner[0].owner_first_name + " " +ownerData.result[0].owner[0].owner_last_name}</h3> }
<h8 style={{paddingLeft: "7rem", paddingTop:"2rem"}}>Owner</h8>
<Navbar/>
</div>
<div>
<Table data={dataTable} column={column} />
</div>
</div>
)
}
My Table Function:
import './table.css'
const Table = ({ data, column }) => {
return (
<table>
<thead>
<tr>
{column.map((item, index) => <TableHeadItem item={item} />)}
</tr>
</thead>
<tbody>
{data.map((item, index) => <TableRow item={item} column={column} />)}
</tbody>
</table>
)
}
const TableHeadItem = ({ item }) => <th>{item.heading}</th>
const TableRow = ({ item, column }) => (
<tr>
{column.map((columnItem, index) => {
return <td>{item[`${columnItem.value}`]}</td>
})}
</tr>
)
export default Table
The issue is in the tbody with data.map but I'm not sure what's wrong as I define my TableRow. I would greatly appreciate any help!

Related

Conditional rendering inside map function ReactJs

I know there's similar thread already but i'm a total newbie and i can't work it. I'm not able include conditional rendering after my map function, do i need some sortf of HTML-tag inbetween?
const renderTableData = () => {
let id = 1;
const activeButton = () => {
}
return (
<tr>
{days.map((val) => (
<td>
{timeSlot.map((n, i) => (
// if(freeSlotsList.includes(id)){ THIS CODE SNIPPET
// return (<h1>Testing</h1> DON'T WORK
// )}
<button id={id++} className={activeButton}> {n} {id}</button>
))}
</td>
))}
</tr>
);
};
EDIT:
i can't seem to access my freeSlotsList, it looks like this
const [freeSlotsList, setFreeSlotsList] = useState([])
useEffect(() => {
Axios.post('http://localhost:3001/api/get/week1/ex').then((response) => {
setFreeSlotsList(response.data)
})
}, [])
Try this, You need to wrap your code into {} if you want to write js code. As () will simply return that as jsx.
const renderTableData = () => {
let id = 1;
const activeButton = () => {
}
return (
<tr>
{days.map((val) => (
<td>
{timeSlot.map((n, i) => {
if(freeSlotsList.includes(id)){
return (<h1>Testing</h1>
)}
return <button id={id++} className={activeButton}> {n} {id}</button>
)}}
</td>
))}
</tr>
);
};

Data from map isn't rendering in React.js

I have successfully gathered data from an API and gathered it in a list, in my return statement the data isn't being rendered, in the console.log it logs fine, the data is there I just can't figure out why it isn't being put on the screen.
Class:
import React, { useEffect, useState } from 'react';
const PokemonRender = () => {
const [pokemonList, setPokemonList] = useState([]);
const tempPokemonArray = []
const getPokemonData = async (id) => {
try {
fetch("https://pokeapi.co/api/v2/pokemon/" + id).then(res => res.json()).then((pokemon) => tempPokemonArray.push(pokemon))
} catch (e) {
console.log(e);
}
};
useEffect((i) => {
for (i = 1; i < 5; i++) {
getPokemonData(i)
}
setPokemonList(tempPokemonArray);
tempPokemonArray.length = 0;
}, []);
return (
<>
<table>
<tbody>
{pokemonList.map(poke=>(
console.log(poke.name),
<tr key={poke.id}>
<td key={1}>{poke.id} Test</td>
<td key={2}>{poke.name} Test 2</td>
</tr>
))}
</tbody>
</table>
</>
)
};
export default PokemonRender;
You need to use Promise.all to gather all the async results from the API and then set the state.
Tips: try not to mix Promise.then().catch() syntax with async/await within a single function. Pick one and stick with it. The async/await is probalby the best option due to its readability and sync-like syntax.
You might also consider adding a isLoading state that will render a "loading..." message or Component while the API is fetching the results.
import React, { useEffect, useState } from 'react';
const PokemonRender = () => {
const [pokemonList, setPokemonList] = useState([]);
const getPokemonData = async (id) => {
try {
const res = await fetch("https://pokeapi.co/api/v2/pokemon/" + id);
const pokemon = await res.json();
return pokemon;
} catch (e) {
console.log(e);
}
};
useEffect((i) => {
const promises = [];
for (let i = 1; i < 5; i++) {
promises.push( getPokemonData(i) )
}
Promise.all(promises).then((results)=>{
setPokemonList(results);
})
}, []);
return (
<>
<table>
<tbody>
{pokemonList.map(poke=>(
<tr key={poke.id}>
<td key={1}>{poke.id} Test</td>
<td key={2}>{poke.name} Test 2</td>
</tr>
))}
</tbody>
</table>
</>
)
};
export default PokemonRender;
Live Snippet
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<script src="https://unpkg.com/react#17/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom#17/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/#babel/standalone/babel.min.js"></script>
</head>
<body>
<div id="root"></div>
<script type="text/babel">
const { useState, useEffect } = React;
const PokemonRender = () => {
const [pokemonList, setPokemonList] = useState([]);
const getPokemonData = async (id) => {
try {
const res = await fetch("https://pokeapi.co/api/v2/pokemon/" + id);
const pokemon = await res.json();
return pokemon;
} catch (e) {
console.log(e);
}
};
useEffect((i) => {
const promises = [];
for (let i = 1; i < 5; i++) {
promises.push( getPokemonData(i) )
}
Promise.all(promises).then((results)=>{
setPokemonList(results);
})
}, []);
return (
<>
<table>
<tbody>
{pokemonList.map(poke=>(
<tr key={poke.id}>
<td key={1}>{poke.id}</td>
<td key={2}>{poke.name}</td>
</tr>
))}
</tbody>
</table>
</>
)
};
ReactDOM.render(
<PokemonRender />,
document.getElementById('root')
);
</script>
</body>
</html>

Why is async await very slow?

I want to make selector for the user to select name of section, and according to what he select, view the section types in another selector, then when he select the section type display the students in a table.
I write code and get the data true but because i use (async..await) so the project get very slow and then closed.
What's the wrong?
function Teacher() {
const [data1, setData1] = useState([]);
const [data2, setData2] = useState([]);
const [data3, setData3] = useState([]);
const [SectionName, setSectionName] = useState('بستان');
const [Type, setType] = useState('أ');
useEffect(() => {
async function getName() {
await Axios
.get(`http://localhost:3003/getSectionsName`)
.then(result => setData1(result.data));
}
getName()
}, []);
const nameSelector = (
<select className="custom-select" onChange={(e) => {
const selectedSectionName = e.target.value;
setSectionName(selectedSectionName);
}}>
{data1.map((item) =>
<option key={item.id} value={item.SectionName}>
{item.SectionName}
</option>
)}
</select>
)
async function typeSelector() {
await Axios.put(`http://localhost:3003/getSectionTypes`, { SectionName: SectionName }).then(result => setData2(result.data))
}
const typeSelect = (
typeSelector(),
<select className="custom-select" onChange={(e) => {
const selectedSectionType = e.target.value;
setType(selectedSectionType);
}}>
{data2.map((item) =>
<option key={item.id}>
{item.Type}
</option>
)}
</select>
)
function student() {
Axios.put(`http://localhost:3003/getStudents`, { Type: Type, SectionName: SectionName }).then(result => setData3(result.data))
}
const studentTable = (
student(),
<table className="table" >
<thead className="thead-dark">
<tr>
<th scope="col">الطلاب</th>
</tr>
</thead>
<tbody>
{data3.map(item => {
return <tr key={item.Id}>
<td>{item.FullName}</td>
</tr>
})}
</tbody>
</table>
)
return (
<div className="container p-2">
<h4> اختر الصف </h4>
{nameSelector}
<br />
<h4> اختر الشعبة </h4>
{typeSelect}
<br /><br />
<h4>
{studentTable}
</h4>
</div>
)
}
export default Teacher;
async function typeSelector() {
await Axios.put(`http://localhost:3003/getSectionTypes`, { SectionName: SectionName }).then(result => setData2(result.data))
}
const typeSelect = (
typeSelector(),
...
is plain wrong - it means you're calling typeSelector() with the comma sequencing operator as a side effect of rendering the component, and likely end up in an infinite render loop. This would happen with a non-async typeSelector() function too.
You will need to wrap those fetch calls within suitable useEffect() hooks, maybe like so (I took the liberty of also extracting the components into, well, components.)
function StudentTable({ students }) {
return (
<table className="table">
<thead className="thead-dark">
<tr>
<th scope="col">الطلاب</th>
</tr>
</thead>
<tbody>
{students.map((item) => {
return (
<tr key={item.Id}>
<td>{item.FullName}</td>
</tr>
);
})}
</tbody>
</table>
);
}
function NameSelector({ sections }) {
return (
<select
className="custom-select"
onChange={(e) => setSectionName(e.target.value)}
>
{sections.map((item) => (
<option key={item.id} value={item.SectionName}>
{item.SectionName}
</option>
))}
</select>
);
}
function TypeSelect({ types }) {
return (
<select
className="custom-select"
onChange={(e) => setType(e.target.value)}
>
{types.map((item) => (
<option key={item.id} value={item.id}>
{item.Type}
</option>
))}
</select>
);
}
function Teacher() {
const [sections, setSections] = useState([]);
const [types, setTypes] = useState([]);
const [students, setStudents] = useState([]);
const [sectionName, setSectionName] = useState("بستان");
const [type, setType] = useState("أ");
// Load sections on mount
useEffect(() => {
Axios.get(
`http://localhost:3003/getSectionsName`,
).then((result) => setSections(result.data));
}, []);
// Load types based on selected section
useEffect(() => {
Axios.put(`http://localhost:3003/getSectionTypes`, {
SectionName: sectionName,
}).then((result) => setTypes(result.data));
}, [sectionName]);
// Load students based on section and type
useEffect(() => {
Axios.put(`http://localhost:3003/getStudents`, {
Type: type,
SectionName: sectionName,
}).then((result) => setStudents(result.data));
}, [sectionName, type]);
return (
<div className="container p-2">
<h4> اختر الصف </h4>
<NameSelector sections={sections} />
<br />
<h4> اختر الشعبة </h4>
<TypeSelect types={types} />
<br />
<br />
<h4>
<StudentTable students={students} />
</h4>
</div>
);
}
export default Teacher;
Try useEffect() that has a dependency sectionName. When it changes, then you will call typeSelector() and student().
const [data1, setData1] = useState([]);
const [data2, setData2] = useState([]);
const [data3, setData3] = useState([]);
const [sectionName, setSectionName] = useState('بستان');
const getName = async () => {
const data = await Axios.get(`http://localhost:3003/getSectionsName`);
setData1(data);
};
const typeSelector = async () => {
const data = await Axios.put(`http://localhost:3003/getSectionTypes`, {
SectionName: SectionName
});
setData2(data);
};
const student = async () => {
const data = Axios.put(`http://localhost:3003/getStudents`, {
Type: Type,
SectionName: SectionName
});
setData3(data);
};
useEffect(() => {
getName();
}, []);
useEffect(() => {
typeSelector();
student();
}, [sectionName]);

change value of input field react

I have an input field in which I am pre populating the value of, with the value from the DB. it is a record that already exists, in which I would like to edit. The input field however, is not letting me edit the field. Please find it below:
import React, { useState, useEffect } from "react";
import axios from "axios";
import { useHistory } from "react-router-dom";
const EditServicesPage = () => {
const history = useHistory()
const [myData, setMyData] = useState({});
const [isLoading, setIsLoading] = useState(false);
const [showEditButton, setShowEditButton] = useState(false);
const [fields, setFields] = useState({
updatedByCNUM: "",
content: "",
site: ""
})
var idFromListServicesPage = history.location.state.id
console.log("22: " + idFromListServicesPage)
useEffect(() => {
axios
.post('/getDocToEdit', {id : idFromListServicesPage})
.then((res) => {
console.log("line 28 esp.js: " + res.data)
setMyData(res.data);
setIsLoading(true);
})
.catch((error) => {
// Handle the errors here
console.log(error);
})
.finally(() => {
setIsLoading(false);
});
}, []);
const deleteById = (id) => {
console.log(id);
axios
.post(`/deleteDoc`, { id: id })
.then(() => {
console.log(id, " worked");
window.location = "/admin/content";
})
.catch((error) => {
// Handle the errors here
console.log(error);
});
};
const handleInputChange = e => setFields(f => ({...f, [e.target.name]: e.target.value}))
const editById = (id, site, content, updatedByCNUM) => {
console.log(id, site, content, updatedByCNUM);
axios
.post(
'/editDoc',
({
id: id,
location: site,
content: content,
updatedByCNUM: updatedByCNUM
})
)
.then(() => {
console.log(id, " worked");
window.location = "/admin/content";
})
.catch((error) => {
console.log(error);
});
};
const onClickEdit = (e, _id) => {
e.preventDefault();
var site = document.getElementById("site").value;
var content = document.getElementById("content").value;
var updatedByCNUM = document.getElementById("updatedByCNUM").value;
console.log(site, content, updatedByCNUM)
editById(_id, site, content, updatedByCNUM);
};
const onTyping = (value) => {
if (value.length > 0) {
setShowEditButton(true);
} else {
setShowEditButton(false);
}
};
return (
<table id="customers">
<h1>Edit Services Page</h1>
<tr>
<th>site</th>
<th>content</th>
<th>updatedByCNUM</th>
<th>Actions</th>
</tr>
<tr>
<td>
<input
// ref={site.ref}
type="text"
value={myData.site}
onInput={(e) => onTyping(e.target.value)}
onChange={handleInputChange}
placeholder={myData.site}
name="site"
id="site"
/>{" "}
{/* <input
type="text"
placeholder={site}
onChange={(e) => onTyping(e.target.value)}
name="site"
id="site"
/> */}
</td>
<td>
<input
// ref={content.ref}
type="text"
value={myData.content}
onInput={(e) => onTyping(e.target.value)}
onChange={handleInputChange}
placeholder={myData.content}
name="content"
id="content"
/>
</td>
<td>
<input
type="text"
placeholder={myData.updatedByCNUM}
name="updatedByupdatedByCNUMhide"
id="updatedByupdatedByCNUMhide"
readOnly
/>{" "}
</td>
<td>
{/* <input type="hidden" placeholder={myData.updatedByCNUM} name="updatedByCNUM" id="updatedByCNUM" value={updatedByCNUM}/>{" "} */}
</td>
<td>
<button
onClick={(e) => {
e.preventDefault();
deleteById(idFromListServicesPage);
}}
disabled={isLoading}
>
Delete
</button>
<button
onClick={(e) => {
e.preventDefault();
editById(idFromListServicesPage);
}}
>
Edit
</button>
{showEditButton && (
<button onClick={(e) => onClickEdit(e, idFromListServicesPage)}>Submit Edit</button>
)}
</td>
</tr>
</table>
);
};
export default EditServicesPage;
showButton:
const onTyping = (value) => {
if (value.length > 0) {
setShowEditButton(true);
} else {
setShowEditButton(false);
}
};
when I try to type into the input field, it doesn't allow me to type, but keeps the pre existing value there already. how can I fix this?
You need a state which has the initial values from the DB
const [data, setData] = useState({
site: newData.site || "",
content: newData.content || "",
});
const handleInputChange = (e) => {
const { name, value } = e.target;
setData((currentData) => ({ ...currentData, [name]: value }));
};
return (
// .....
<input
// ref={site.ref}
type="text"
value={data.site} // use data.site here instead of the newData
onChange={handleInputChange}
placeholder={myData.site}
name="site"
id="site"
/>
// .....
);
Just add setMyData like this:
const onTyping = (name, value) => {
setMyData({ ...myData, [name]: value });
if (value.length > 0) {
setShowEditButton(true);
} else {
setShowEditButton(false);
}
};
And
onInput={(e) => onTyping(e.target.name, e.target.value)}

How can i React ( get axios from Json and ReRandering my page)

Why am I asking this question (main return) is finsied, but board.writer is not drawing. how can i drawing this object
if my question is wrong way plz tell me . i will fix it
i tried this way
first use map function
make like this function renderUser = ({board_SEQ, content, writer,subject}) => { parameter}
const Home = () => {
const initboard = {
board_SEQ: '',
writer: '',
content: '',
subject: ''
};
const [boards, setBoard] = useState([]);
const load = () => {
axios.get('http://www.heon.shop:8080/api/boards')
.then((res) => {
const data = res.data;
setBoard(boards => [...boards, {
board_SEQ: (data[0].board_SEQ),
writer: data[0].writer,
content: data[0].content,
subject: data[0].subject
}]);
})
.catch((error) => {
console.log("error" + error);
}
);
}
useEffect(() => {
load();
console.log("useEffect");
}, []);
const renderUser = ({board_SEQ, content, writer, subject}) => {
return (
<div>
<li>he</li>
<li>{board_SEQ}</li>
<li>{content}</li>
<li>{writer}</li>
<li>{subject}</li>
</div>
);
}
return (
<div>
{boards.map(board => {
<h1> {board.writer}</h1>
})}
</div>
);
}
export default Home;
Maybe you can try like this,
<div>
{boards.map(board => renderUser(board)}
</div>
if you want to render item directly using (add return to the map):
<div>
{boards.map(board => {
return <h1> {board.writer}</h1>;
})}
</div>