Conditional rendering inside map function ReactJs - html

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>
);
};

Related

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>

how to add css for div in React?

how to add css in such a way whenever i click and select on div the border and background colors of the div should be changed same goes for all for the selected and should be back to previous if deselected.
This is a seemingly stupid question, but I'm not a pro when it comes to css. I have created a multiple div for multiple selection of div, but the css file that came with it has completely changed the look of it and it looks different to my other controls - Is there a simple way of inheriting the look of another control?
codesanbox
I tried this way
const data = [
{
key: 1,
value: "four"
},
{
key: 2,
value: "fours"
}
];
export default function App() {
const initialState = data.map((item) => {
return { ...item, selected: false };
});
const [work, setWork] = React.useState(initialState);
const [state, setState] = React.useState();
const [selected, setSelected] = React.useState("");
console.log("work");
console.log(work);
console.log("work");
console.log("state");
console.log(state);
console.log("state");
React.useEffect(() => {
setState(
work.filter((person) => person.selected).map((person) => person.value)
);
setSelected(
work.filter((person) => person.selected).map((person) => person.value)
);
}, [work]);
const handleSelect = (value) => {
console.log("value", value);
const nextState = work.map((item) => {
if (item.value === value) {
return {
...item,
selected: !item.selected
};
}
return item;
});
setWork(nextState);
};
return (
<div className="parent">
{work.map((da) => (
<div
className={`child ${selected === da.value ? "selected" : ""}`}
onClick={() => handleSelect(da.value)}
>
{da.value}
</div>
))}
</div>
);
}
I've done slight modifications in the code.
Following code would help you get the desired results.
const handleSelect = (key) => {
const updatedItems = [];
work.forEach((item) => {
updatedItems.push ({
...item,
selected: item.key === key
});
});
setWork(updatedItems);
};
return (
<div className="parent">
{work.map((da) => (
<div
className={`child ${da.selected ? "selected" : ""}`}
onClick={() => handleSelect(da.key)}
>
{da.value}
</div>
))}
</div>
);

Fetch data.slice is not a function issue

I have a problem with slicing my json. I was using data.json and everything worked fine, but when I'm trying to use the same with fetch. Console tells me that data.slice is not a function. This is my code in React:
const left = '<';
const right = '>';
const { currentPage, usersPerPage } = this.state;
const lastPage = currentPage * usersPerPage;
const firstPage = lastPage - usersPerPage;
const data = fetch('https://jsonplaceholder.typicode.com/photos')
.then(response => response.json());
const currentPhotos = data.slice(firstPage, lastPage);
const renderPhotos = currentPhotos.map((photo) => {
return <tr key={photo.id}>
<td className="number">{photo.title}</td>
</tr>
});
const numbers = [];
for (let i = 1; i <= Math.ceil(data.length / usersPerPage); i++) {
numbers.push(i);
}
const renderPagination = numbers.map(number => {
return (
<li className="controls" key={number} id={number} onClick={this.handlePages}>
{number}
</li>
);
});
fetch is async, which means it returns a promise.
const data = fetch('https://jsonplaceholder.typicode.com/photos')
.then(response => response.json())
.then(json => console.log(json));
the constant data here is a Promise. which awaits to get resolved, to get your code to work you either have to use async/await like this:
const data = await fetch('https://jsonplaceholder.typicode.com/photos')
.then(response => response.json())
.then(json => console.log(json));
and you will also have to add the async keyword to your top function that wraps your code, but if this is a website you'll need to use babel for this to work in all browsers.
another take is using the callback technique but you will have to do some rewrite, but here is a start:
fetch('https://jsonplaceholder.typicode.com/photos')
.then(response => response.json())
.then(data => {
const currentPhotos = data.slice(firstPage, lastPage);
const renderPhotos = currentPhotos.map((photo) => {
return <tr key={photo.id}>
<td className="number">{photo.title}</td>
</tr>
});
});
fetch returns a Promise, so if you want to use slice method, you should use it inside the last .then(), but it would be better if you fetch your data in componentDidMount, save your data in React state, and after that use in render method;
for example, your code should look like:
componentDidMount() {
fetch('https://jsonplaceholder.typicode.com/photos')
.then(response => {
const data = response.json();
this.setState({
data: data,
});
);
}
render() {
const { currentPage, usersPerPage, data } = this.state;
const currentPhotos = data.slice(firstPage, lastPage);
const renderPhotos = currentPhotos.map((photo) => (
<tr key={photo.id}>
<td className="number">{photo.title}</td>
</tr>
);
const numbers = [];
for (let i = 1; i <= Math.ceil(data.length / usersPerPage); i++) {
numbers.push(i);
}
const renderPagination = numbers.map(number => {
return (
<li className="controls" key={number} id={number} onClick={this.handlePages}>
{number}
</li>
);
});
}