React-Redux: Add quantity value to a table in order/cart - javascript

I am trying to create a purchase order screen and I am facing issues while adding the quantity of the product.
Workflow
a)Fetch the product details from state and get in the drop down. Select the product from drop down
b)Add the quantity in the text field. Click on Add
c)This will add the product details to a table.
But I am not sure how to set a constant quantity for each product selected.
Now when I am not sure how to add the quantity to the product selected.
Sorry, the code might be messed up, I am still learning. Adding the code below.
let count=0;
const [validated, setValidated] = useState(false);
const dispatch = useDispatch()
const [medicineName, setMedicineName] = useState('')
const [quantity, setQuantity] = useState(0)
const [tableData, setTableData] = useState([])
const productList = useSelector( state => state.productList )
const { loading, error, products } = productList
const userLogin = useSelector(state => state.userLogin)
const {userInfo} = userLogin
const [dropDownData, setDropDownData] = useState(products)
useEffect(()=>{
setDropDownData(products)
},[products])
useEffect(() => {
if(!userInfo){
history.push('/login')
}
dispatch(listProducts())
},[dispatch, history, userInfo])
const submitHandler = (e) => {
e.preventDefault()
const arr = dropDownData.filter((product) =>
product.medicineName.toLowerCase().indexOf(medicineName.toLowerCase()) > -1)
setTableData(tableData => tableData.concat(arr))
const arr2 = dropDownData.filter((product) =>
product.medicineName.toLowerCase().indexOf(medicineName.toLowerCase()))
setDropDownData(arr2)
}
return(
<>
<h2>PurchaseOrderScreen</h2>
<Form onSubmit={submitHandler} validated={validated} noValidate>
<Row>
<Col md={7}>
<Form.Group controlId='medicineName'>
<FloatingLabel controlId="floatingSelect" label="Medicine">
<Form.Control as='select' value={medicineName} className="mb-3"
onChange={(e) => setMedicineName(e.target.value)}
required
>
<option value=''>Select Medicine</option>
{dropDownData.map(product => (
<option value={product.medicineName}>{product.medicineName}</option>
)) }
</Form.Control>
</FloatingLabel>
</Form.Group>
</Col>
<Col md={3}>
<Form.Group className="mb-3" controlId='quantity'>
<FloatingLabel controlId="floatingInput" label="Quantity" >
<Form.Control type="text" placeholder="Quantity"
value={quantity}
onChange = {(e)=> setQuantity(e.target.value)}
required
/>
</FloatingLabel>
</Form.Group>
</Col>
<Col md={2}>
<Button type='submit' variant='primary'>
>Add
</Button>
</Col>
</Row>
</Form>
<Table striped bordered hover responsive='md' className='table-sm mt-3' id="table-to-xls">
<thead>
<tr>
<th><span className='btn'>Remove</span></th>
<th ><span className='btn'>Sl</span></th>
<th ><span className='btn'>Medicine</span></th>
<th ><span className='btn'>C.stock</span></th>
<th ><span className='btn'>Quantity</span></th>
<th ><span className='btn'>Low Stock</span></th>
<th ><span className='btn'>Reorder Quantity</span></th>
</tr>
</thead>
<tbody>
{tableData.map(product => (
<tr key={product._id} >
<td> X </td>
<td>{count+1}</td>
<td>{product.medicineName}</td>
<td>{product.currentStock}</td>
<td>{quantity}</td>
<td>{product.lowStockValue}</td>
<td>{product.reOrderValue}</td>
</tr>
)) }
</tbody>
</Table>
Can you please let me know how the quantity can be added. Please let me know if you need any details.

In order to add the quantity to the table, you need to store it somewhere. You have an array called tableData that you currently are adding your products to. Maybe instead of adding the products, you could add an object:
// Inside the submitHandler function
const productToAdd = dropDownData.find((product) =>
product.medicineName.toLowerCase().indexOf(medicineName.toLowerCase()) > -1);
const rowToAdd = {product: productToAdd, quantity: quantity};
setTableData(tableData => [...tableData, rowToAdd])
and then later in your render:
{tableData.map(row => (
<tr key={row.product._id} >
<td> X </td>
<td>{count+1}</td>
<td>{row.product.medicineName}</td>
<td>{row.product.currentStock}</td>
<td>{row.quantity}</td>
<td>{row.product.lowStockValue}</td>
<td>{row.product.reOrderValue}</td>
</tr>
)) }

Related

Searching in Database and showing in react table

I have this code in PHP which has path "http://localhost:80/ico/vypsani.php"
$ico = $_POST['ico'];
include_once("core.php");
$sql = "SELECT * FROM ico WHERE ico = '$ico'";
$result = mysqli_query($conn, $sql);
$json_array = array();
while($row = mysqli_fetch_assoc($result)){
$json_array[]=$row;
}
echo json_encode($json_array);
in PHP I am searching row in database with input in React and its working, but I need to ge it into this table
import React,{useState, useEffect} from 'react';
const Data = () =>{
const [item, setItem] = useState([]);
useEffect(()=>{
fetch("http://localhost:80/ico/vypsani.php")
.then(res => res.json())
.then(
(result) => {
setItem(result);
}
)
},[])
return (
<div className="row">
<table class="table table-striped table-dark">
<thead className='thead-dark'>
<tr>
<th scope="col">ID</th>
<th scope="col">IČO</th>
<th scope="col">Název</th>
<th scope="col">Město</th>
<th scope="col">Ulice</th>
<th scope="col">Číslo Domovní</th>
<th scope="col">Číslo Orientační</th>
<th scope="col">Datum uložení</th>
</tr>
</thead>
<tbody>
{
item.map(item=>(
<tr key={item.ID}>
<td>{item.ID}</td>
<td>{item.ico}</td>
<td>{item.nazev}</td>
<td>{item.mesto}</td>
<td>{item.ulice}</td>
<td>{item.cisloDomovni}</td>
<td>{item.cisloOrientacni}</td>
<td>{item.datum}</td>
</tr>
))
}
</tbody>
</table>
</div>
);
}
but it shows the row from database like this and not in react table, I think because of the POST.
How react app looks like
import React from 'react';
import './App.css';
import Data from "./data/data.js";
function App() {
return (
<div className="App">
<form action='http://localhost:80/ico/vypsani.php' method="post">
<div className='form'>
<h1>IČO</h1>
<input name="ico" onKeyPress={(event) => {
if (!/[0-9]/.test(event.key)) {
event.preventDefault();
alert("Zadávat lze pouze čísla")
}
}}
/>
<h1>Název firmy</h1>
<input name="nazev" type="text"></input>
<br></br>
<button type="submit" name='submit' value="vyhledat">Vyhledat</button>
<br></br>
<button type="submit" name='submit' value="odeslat">Odeslat</button>
<br></br>
</div>
<h1>Výpis z Databáze</h1>
<Data/>
</form>
</div>
);
}
export default App;
POSTing form to php page is not the correct way to do this. Please read answer to this question: Send a ReactJS form to a PHP page
To get your code to work, you can remove form in the html and handle the request using fetch only.
Also, change $ico = $_POST['ico']; to $ico = $_GET['ico']; in your php file
import React from 'react';
class Test extends React.Component {
constructor(props) {
super(props);
this.state = {
tableData: [],
ico: ''
};
}
handleInput = event => {
this.setState({ ico: event.target.value });
};
logValue = () => {
fetch("http://localhost:80/ico/vypsani.php?ico=" + this.state.ico)
.then(res => res.json())
.then(
(result) => {
this.setState(state => state.tableData = result);
}
)
.catch(err => {
throw err
});
};
render() {
return (
<div className="App">
<div className='form'>
<h1>IČO</h1>
<input name="ico" onKeyPress={(event) => {
if (!/[0-9]/.test(event.key)) {
event.preventDefault();
alert("Zadávat lze pouze čísla")
}
}}
/>
<h1>Název firmy</h1>
<input name="nazev" onChange={this.handleInput} type="text"></input>
<br></br>
<button type="submit" name='submit' onClick={this.logValue} value="vyhledat">Vyhledat</button>
<br></br>
<button type="submit" name='submit' value="odeslat">Odeslat</button>
<br></br>
</div>
<h1>Výpis z Databáze</h1>
<div >
<table class="table table-striped table-dark">
<thead className='thead-dark'>
<tr>
<th scope="col">ID</th>
<th scope="col">IČO</th>
<th scope="col">Název</th>
<th scope="col">Město</th>
<th scope="col">Ulice</th>
<th scope="col">Číslo Domovní</th>
<th scope="col">Číslo Orientační</th>
<th scope="col">Datum uložení</th>
</tr>
</thead>
<tbody>
{
this.state.tableData.map(item => (
<tr key={item.ID}>
<td>{item.ID}</td>
<td>{item.ico}</td>
<td>{item.nazev}</td>
<td>{item.mesto}</td>
<td>{item.ulice}</td>
<td>{item.cisloDomovni}</td>
<td>{item.cisloOrientacni}</td>
<td>{item.datum}</td>
</tr>
))
}
</tbody>
</table>
</div>
</div>
);
}
}
export default Test;
Change your useEffect like this
useEffect(()=>{
fetch("http://localhost:80/ico/vypsani.php")
.then(result => {
setItem(result);
console.log(result);
}
)
.catch(error => {
console.log(error)
})
},[])
and table body like this
<tbody>
{
item && item?.map(ele=>(
<tr key={ele.ID}>
<td>{ele.ID}</td>
<td>{ele.ico}</td>
<td>{ele.nazev}</td>
<td>{ele.mesto}</td>
<td>{ele.ulice}</td>
<td>{ele.cisloDomovni}</td>
<td>{ele.cisloOrientacni}</td>
<td>{ele.datum}</td>
</tr>
))
}
</tbody>

Trying to delete Row from table using react.js

So what I have done here is created a table with 5 ByDefault rows for that aI created a array with 5 elements and mapped over it and I got the rows. After that I created an input field in which user can enter the number of extra rows they want, using the "increaseRow" function and the user input I push Elements in the array so that i can get that number of rows and got it as well. But when I Keep the By Default rows as it is and some new rows e.g 5 rows and try to DELETE all 10 rows it creates problem
All I want is the rows should get DELETED.
import { useState } from "react";
import Table from "react-bootstrap/Table";
import './App.css'
const App = () => {
const row1 = [];
const [row, setRow] = useState();
const [NewRow, setNewRow] = useState([1,2,3,4,5]);
const [allRowsAdded, updateAllRows] = useState(0);
const addRow = (e) => {
e.preventDefault();
setRow(e.target.value);
};
const increaseRow = () => {
for (let i = 0; i < parseInt(row); i++) {
row1[i] = allRowsAdded + i;
}
updateAllRows((allRowsAdded) => allRowsAdded + parseInt(row));
setNewRow([...NewRow, ...row1]);
};
const deleteRow = (id) => {
const updatedRows = [...NewRow].filter((rowId) => {
return rowId !== id;
});
setNewRow(updatedRows);
};
return (
<>
<div>
<form>
<input type="text" onChange={addRow} placeholder="Enter Number Of Row's" /><br />
</form>
<button onClick={increaseRow}> Add </button>
</div>
<div className="container">
<form >
<Table striped bordered hover responsive variant="light">
<thead>
<tr>
<th>
{" "}
<h6> No. </h6>{" "}
</th>
<th>
{" "}
<h6> Injection Speed </h6>{" "}
</th>
<th>
{" "}
<h6> Fill Time </h6>{" "}
</th>
<th>
{" "}
<h6> Peak Inj Press </h6>{" "}
</th>
<th>
{" "}
<h6> Viscocity </h6>{" "}
</th>
<th>
{" "}
<h6> Shear Rate </h6>{" "}
</th>
<th>
{" "}
<h6> AbsoluteDropViscocity </h6>{" "}
</th>
<th>
{" "}
<h6> %DropViscocity </h6>{" "}
</th>
<th>
{" "}
<h6> Action </h6>{" "}
</th>
</tr>
</thead>
<tbody className="grid_style">
{NewRow.map((rowId) => {
return (
<tr key={rowId}>
<td> {rowId} </td>
<td>
<input type="text" className="form-control" />
</td>
<td>
<input type="text" className="form-control" />
</td>
<td>
<input type="text" className="form-control" />
</td>
<td>
<input type="text" className="form-control" readOnly />
</td>
<td>
<input type="text" className="form-control" readOnly />
</td>
<td>
<input type="text" className="form-control" readOnly />
</td>
<td>
<input type="text" className="form-control" readOnly />
</td>
<td>
<i
className="fa fa-trash viscocity_icons"
onClick={() => deleteRow(rowId)}
>
</i>
</td>
</tr>
);
})}
</tbody>
</Table>
</form>
</div>
</>
);
};
export default App;
https://codesandbox.io/s/silly-allen-iun6b?file=/src/App.js
This is just a logical error (rowId clashes) that you are doing.
const increaseRow = () => {
for(let i=0; i < row; i++){
row1[i] = i;
}
setNewRow([...NewRow, ...row1]);
}
Here when u are assigning value to a row, you are taking index as id for that row. According to which, this is happening with rowId
and on removing a row and filtering based on rowId, for eg: id=1
const deleteRow = (id) => {
const updatedRows = NewRow.filter((rowId) => {
return rowId!== id;
})
setNewRow(updatedRows)
}
2 rows are removed with rowId=1, ie. at serial number 1 and 6.
Solution
You can correct this by adding anything for unique Keys, like uuid. Here I have used an extra state variable const [allRowsAdded, updateAllRows] = useState(0); which stores the total number of rows added from now and add the rowIds next to the addedRows.
const increaseRow = () => {
for (let i = 0; i < parseInt(row); i++) {
row1[i] = allRowsAdded + i;
}
updateAllRows((allRowsAdded) => allRowsAdded + parseInt(row));
setNewRow([...NewRow, ...row1]);
};
Now, rowIds becomes
And there will be no rowId clashes.
Code Link : https://codesandbox.io/s/quiet-snowflake-26v1o?file=/src/App.js
here is by my understanding will work,
const deleteRow = (id) => {
const updatedRows = NewRow.filter((index) => {
return index !== id;
})
setNewRow(updatedRows)
}
change your html code,
<td> <i className="fa fa-trash viscocity_icons" onClick={() => deleteRow(index)}></i> </td>
i dont know about datastructure or json of array,
const deleteRow = (id) => {
const updatedRows = NewRow.filter((e) => {
return e.id !== id;
})
setNewRow(updatedRows)
}

Rendering data that being passed from parent component to a modal children on react

I have an array of object that i got from my API and then displayed them to parent component as table row like so :
review.js
Each row has its own edit button where when i click ,it will popup a modal ( not redirecting to another page ) and it will contain some information based on which row i click.
Below is the example when i click the forth row which has "Mamang Racing" as the client name.
reviewDetailModal.js
The Problem is , on the children component (modal component) when i about to edit any other rows for some reason it will still show me the latest data ( in this case the forth row ).
Code is shown below :
review.js
const Review = () => {
const [showModal, setShowModal] = useState("close");
const [review, setReview] = useState([]);
const handleClose = () => setShowModal("close");
const handleShowModalOne = () => setShowModal("modal-one");
const handleShowModalTwo = () => setShowModal("modal-two");
useEffect(() => {
let isMounted = false;
const FetchReview = async () => {
await publicAxios
.get("/api/review/")
.then((result) => {
setReview(result.data);
})
.catch((err) => console.log(err));
};
FetchReview();
console.log(review);
return () => {
isMounted = true;
};
}, []);
return (
<Layout>
<Container fluid style={{ overflowY: "auto", paddingTop: "10px" }}>
<div className="d-flex flex-row-reverse">
<Button
variant="success"
className="mb-2"
onClick={handleShowModalOne}
>
<FaPlusCircle /> Add Testimonial
</Button>
<AddReviewModal isShow={showModal} isClose={handleClose} />
</div>
<Table striped bordered hover className="text-center">
<thead>
<tr>
<th>Client</th>
<th>Review</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{review.map((item) => (
<tr key={item._id}>
<td className="align-middle">{item.clientName}</td>
<td className="align-middle">{item.projectName} </td>
<td style={{ width: "200px" }} className="align-middle">
<Button variant="primary" className="m-1 ">
<FaEye />
</Button>
<Button
variant="warning"
className="m-1"
onClick={handleShowModalTwo}
>
<FaPenSquare />
</Button>
<ReviewDetailModal
data={item}
isShow={showModal}
isClose={handleClose}
/>
<Button variant="danger" className="m-1">
<FaTrashAlt />
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</Container>
</Layout>
);
};
reviewDetailModal.js
const ReviewDetailModal = ({ data, isShow, isClose }) => {
return (
<Modal show={isShow === "modal-two"} onHide={isClose}>
<Modal.Header>
<Modal.Title>Edit Review</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="form.InputName">
<Form.Label>Your Name</Form.Label>
<Form.Control
type="text"
placeholder="Nama Anda"
defaultValue={data.clientName}
/>
</Form.Group>
<Form.Group controlId="form.InputName">
<Form.Label>Project Name</Form.Label>
<Form.Control
type="text"
placeholder="Nama Anda"
defaultValue={data.projectName}
/>
</Form.Group>
<Form.Group controlId="form.Rating">
<Form.Label>Tinggalkan Rating : </Form.Label>
<Form.Control as="select" defaultValue={data.rating}>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</Form.Control>
</Form.Group>
<Form.Group controlId="form.TextArea">
<Form.Label>Kalimat Review</Form.Label>
<Form.Control
as="textarea"
rows={3}
defaultValue={data.description}
/>
</Form.Group>
<Form.Group>
<label>Foto Anda</label>
<Form.File id="pictureFile" />
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button onClick={isClose}>Close</Button>
</Modal.Footer>
</Modal>
);
};
API Result , one of my data :
Array(4) [ {…}, {…}, {…}, {…} ]
0: Object { _id: "60c18f1de4579e22d0e636cb", clientName: "pak dwek", projectName: "Landing Page Pakdwek", … }
__v: 0
_id: "60c18f1de4579e22d0e636cb"
clientName: "pak dwek"
createdAt: "2021-06-10T04:03:41.594Z"
description: "Sangat Baik , pelayanan memuaskan"
photo: "img/pakdhe.jpg"
projectName: "Landing Page Pakdwek"
score: 5
updatedAt: "2021-06-10T04:03:41.594Z"
<prototype>: Object { … }
1: Object { _id: "60c34afac1bdda333840a1cb", clientName: "alex", projectName: "landing page alex", … }
__v: 0
_id: "60c34afac1bdda333840a1cb"
clientName: "alex"
createdAt: "2021-06-11T11:37:30.852Z"
description: "sangat baik"
photo: "https://res.cloudinary.com/rembux-developer/image/upload/v1623411449/review-photos/ipbqv8xxqfs45yx9s5kz.jpg"
projectName: "landing page alex"
rating: 4
updatedAt: "2021-06-11T11:37:30.852Z"
<prototype>: Object { … }
2: Object { _id: "60c34b7ec1bdda333840a1cc", clientName: "Suhardono", projectName: "Project Web APp", … }
__v: 0
_id: "60c34b7ec1bdda333840a1cc"
clientName: "Suhardono"
createdAt: "2021-06-11T11:39:42.456Z"
description: "buruk"
photo: "https://res.cloudinary.com/rembux-developer/image/upload/v1623411581/review-photos/hkxt98hm28sb6sgc3wao.jpg"
projectName: "Project Web APp"
rating: 2
updatedAt: "2021-06-11T11:39:42.456Z"
<prototype>: Object { … }
3: Object { _id: "60c6d7a5eca83317bc8d0c5c", clientName: "Mamang Racing", projectName: "Test Project", … }
__v: 0
_id: "60c6d7a5eca83317bc8d0c5c"
clientName: "Mamang Racing"
createdAt: "2021-06-14T04:14:29.910Z"
description: "Bagusssss"
photo: "https://res.cloudinary.com/rembux-developer/image/upload/v1623644068/review-photos/sdha9mu1r6a3jvjfbqpm.png"
projectName: "Test Project"
rating: 3
updatedAt: "2021-06-14T04:14:29.910Z"
<prototype>: Object { … }
length: 4
You have to create a save method & pass the modal data through that save method to Review component.
review.js
const Review = () => {
const [showModal, setShowModal] = useState("close");
const [review, setReview] = useState([]);
const handleClose = () => setShowModal("close");
const handleShowModalOne = () => setShowModal("modal-one");
const handleShowModalTwo = () => setShowModal("modal-two");
useEffect(() => {
let isMounted = false;
const FetchReview = async () => {
await publicAxios
.get("/api/review/")
.then((result) => {
setReview(result.data);
})
.catch((err) => console.log(err));
};
FetchReview();
console.log(review);
return () => {
isMounted = true;
};
}, []);
const onChangeReview = (index, obj) => {
setReview((prev) =>
prev.map((item, i) => (i === index ? { ...item, ...obj } : item))
);
}; // Update the state using the modal submitted data
return (
<Layout>
<Container fluid style={{ overflowY: "auto", paddingTop: "10px" }}>
<div className="d-flex flex-row-reverse">
<Button
variant="success"
className="mb-2"
onClick={handleShowModalOne}
>
<FaPlusCircle /> Add Testimonial
</Button>
<AddReviewModal isShow={showModal} isClose={handleClose} />
</div>
<Table striped bordered hover className="text-center">
<thead>
<tr>
<th>Client</th>
<th>Review</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{review.map((item, index) => (
<tr key={item._id}>
<td className="align-middle">{item.clientName}</td>
<td className="align-middle">{item.projectName} </td>
<td style={{ width: "200px" }} className="align-middle">
<Button variant="primary" className="m-1 ">
<FaEye />
</Button>
<Button
variant="warning"
className="m-1"
onClick={handleShowModalTwo}
>
<FaPenSquare />
</Button>
<ReviewDetailModal
index={index} {/* Pass the index of the item */}
data={item}
isShow={showModal}
isClose={handleClose}
onChangeReview={onChangeReview} {/* Pass the handler as an prop */}
/>
<Button variant="danger" className="m-1">
<FaTrashAlt />
</Button>
</td>
</tr>
))}
</tbody>
</Table>
</Container>
</Layout>
);
};
reviewDetailModal.js
const ReviewDetailModal = ({
index,
data,
isShow,
isClose,
onChangeReview
}) => {
const name = useRef(null);
const project = useRef(null);
const rate = useRef(null);
const review = useRef(null);
const picture = useRef(null); // Creating references to Modal form fields
const onSave = () => {
onChangeReview(index, {
clientName: name.current.value,
projectName: project.current.value,
score: rate.current.value,
review: review.current.value, // review info not exist in API returned array
photo: picture.current.value
});
}; // Model data save handler
return (
<Modal show={isShow === "modal-two"} onHide={isClose}>
<Modal.Header>
<Modal.Title>Edit Review</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form>
<Form.Group controlId="form.InputName">
<Form.Label>Your Name</Form.Label>
<Form.Control
type="text"
placeholder="Nama Anda"
defaultValue={data.clientName}
ref={name} {/* Pass the references to the the form fields */}
/>
</Form.Group>
<Form.Group controlId="form.InputName">
<Form.Label>Project Name</Form.Label>
<Form.Control
type="text"
placeholder="Nama Anda"
defaultValue={data.projectName}
ref={project}
/>
</Form.Group>
<Form.Group controlId="form.Rating">
<Form.Label>Tinggalkan Rating : </Form.Label>
<Form.Control as="select" defaultValue={data.rating} ref={rate}>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</Form.Control>
</Form.Group>
<Form.Group controlId="form.TextArea">
<Form.Label>Kalimat Review</Form.Label>
<Form.Control
as="textarea"
rows={3}
defaultValue={data.description}
ref={review}
/>
</Form.Group>
<Form.Group>
<label>Foto Anda</label>
<Form.File id="pictureFile" ref={picture} />
</Form.Group>
</Form>
</Modal.Body>
<Modal.Footer>
<Button onClick={onSave}>Save</Button>{" "}
{/* Add the Save handler to onClick */}
<Button onClick={isClose}>Close</Button>
</Modal.Footer>
</Modal>
);
};
Let me know if you need further support.
Try this approach,
Update the selected record info in the local state and pass that info into the model.
import React, { useState } from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import { Modal, Button } from "react-bootstrap";
const data = [
{
id: 1001,
firstname: "Mark",
lastname: "Otto",
age: 34,
location: "London",
address: "10 Downing Street"
},
{
id: 1002,
firstname: "Jacob",
lastname: "Snow",
age: 34,
location: "India",
address: "#110 broad Street"
},
{
id: 1003,
firstname: "Sarun",
lastname: "U K",
age: 30,
location: "USA",
address: "#1 NY"
}
];
function App() {
const [show, setShow] = useState(false);
const [selectedData, setSelectedData] = useState({});
const hanldeClick = (selectedRec) => {
setSelectedData(selectedRec);
setShow(true);
};
const hideModal = () => {
setShow(false);
};
return (
<div className="App">
<table class="table">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Location</th>
<th scope="col">Show More</th>
</tr>
</thead>
<tbody>
{data.map((v) => (
<tr>
<td>{v.id}</td>
<td>{v.firstname}</td>
<td>{v.lastname}</td>
<td>#{v.location}</td>
<td>
<a href="#" onClick={() => hanldeClick(v)}>
More details
</a>
</td>
</tr>
))}
</tbody>
</table>
<Dialog show={show} details={selectedData} handleClose={hideModal} />
</div>
);
}
const Dialog = ({ show, handleClose, details }) => {
return (
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>
{details?.firstname} {details?.lastname}
</Modal.Title>
</Modal.Header>
<Modal.Body>
<table class="table">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Age</th>
<th scope="col">Location</th>
<th scope="col">Address</th>
</tr>
</thead>
<tbody>
<tr>
<td>{details?.id}</td>
<td>{details?.firstname}</td>
<td>{details?.lastname}</td>
<td>{details?.age}</td>
<td>{details?.location}</td>
<td>{details?.address}</td>
</tr>
</tbody>
</table>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleClose}>
Close
</Button>
<Button variant="primary" onClick={handleClose}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
);
};
export default App;
Sample codesandbox - https://codesandbox.io/s/react-model-dialog-box-askavy-forked-7uf94?file=/src/App.js:0-2922

How to dynamically update the components in ReactJS

I am new to React and I don't know how to overcome the below situation.
Let say I have to display a table.In Table <td> i have one dropdown which I got from my child component.And also have some <div> next to the dropdown.
So,for each dropdown change, i have to bind some html into that <div>.Below line is working for very first dropdown change.
ReactDOM.render(myHtml, document.getElementById(myID));
So For a second time it is not render the new html.
Kindly correct me If I did anything wrong and give me some suggestion to overcome the above issue.
Thanks in Advance.
class Home extends Component{
state = {
tableDetails:'',
};
LoadTableDetails = () => {
const getUrl = "Some API Url";
let dd= fetch(getUrl);
dd.then(response => {
return response.json();
}).then(items => {
var body = this.getTableBody(items);
this.setTableDetails(body);
});
}
getTableBody(items){
let body ;
if(items != null){
body = items.map((folder,index) =>
<tr key={index}>
<td>{folder.FolderName}</td>
<td>
<MyDropDown fileNames={folder.FileNames} folderFiles={folder.FolderFiles} id={folder.FolderName.replace(/ /g,'_')} setSelectedFile = {this.setSelectedFile}/> // Here I get dropdown selected value and see setSelectedFile method
</td>
<td>
<div id={folder.FolderName.replace(/ /g,'_')}>
////I need some html here based on the above dropdown change
</div>
</td>
<td></td>
</tr>
);
}
return folderItems;
}
setTableDetails(body){
let dd = (<div className="container" >
<h2 class="text-center">Server Details</h2>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Folder</th>
<th scope="col">Config Files</th>
<th scope="col">Config Section</th>
<th scope="col">App Settings</th>
</tr>
</thead>
<tbody>
{body}
</tbody>
</table>
</div>);
this.setState({tableDetails:dd});
}
setSelectedFile = (val) =>{
const getUrl = 'my url';
let loadItems = fetch(getUrl);
loadItems.then(response=>{
return response.json();
}).then(data=>{
let configHtml = (
<div>
<MyDropDown fileNames={data} id={val.id + path.replace('\\','_').replace('/\//g','_')} path={path} setSelectedFile = {this.getConfigSectionDetails}/>
<div className="mt-4" id={val.id + path.replace('\\','_').replace('/\//g','_')}>
</div>
</div>
);
let id = val.id; //This is the id where my new
ReactDOM.render(configHtml, document.getElementById(id)); //this line is working for my first dropdown change.If I change the dropdown again then it is not rerenered
});
}
render(){
return (
<div class="mt-4">
<div class="input-group-append">
<button class="btn btn-info" type="button" onClick={this.LoadTableDetails}>Load Table Details</button>
</div>
{this.state.tableDetails}
</div>
);
}
}
export default Home;
I got my Answer.We have to use our states to update the values and not html.
class Home extends Component{
state = {
tableDetails:'',
dropdownDetails:''
};
LoadTableDetails = () => {
const getUrl = "Some API Url";
let dd= fetch(getUrl);
dd.then(response => {
return response.json();
}).then(items => {
this.setState({
tableDetails:items
});
});
}
getTableDetails = (items)=>{
return (<div className="container" >
<h2 class="text-center">Server Details</h2>
<table class="table">
<thead class="thead-dark">
<tr>
<th scope="col">Folder</th>
<th scope="col">Config Files</th>
<th scope="col">Config Section</th>
<th scope="col">App Settings</th>
</tr>
</thead>
<tbody>
{
items.map((folder,index) =>{
return (<tr key={index}>
<td>{folder.FolderName}</td>
<td>
<MyDropDown fileNames={folder.FileNames} folderFiles={folder.FolderFiles} id=index setSelectedFile ={this.setSelectedFile}/>
</td>
<td>
<div>
{this.getConfigHtml(this.state.dropdownDetails)}
</div>
</td>
<td></td>
</tr>)
})
}
</tbody>
</table>
</div>);
}
getConfigHtml =(val)=>{
return (
<div>
<MyDropDown fileNames={val.data} path={val.path} setSelectedFile = {this.getConfigSectionDetails}/>
</div>
);
}
setSelectedFile = (val) =>{
const getUrl = 'my url';
let loadItems = fetch(getUrl);
loadItems.then(response=>{
return response.json();
}).then(data=>{
let val={
data:data,
path:val.path
};
this.setState({dropdownDetails:val});
});
}
render(){
return (
<div class="mt-4">
<div class="input-group-append">
<button class="btn btn-info" type="button" onClick={this.LoadTableDetails}>Load Table Details</button>
</div>
{this.getTableDetails(this.state.tableDetails)}
</div>
);
}
}
export default Home;

Nothing was returned from render in React JS

I am doing a call for an API (fake, just for testing), but i recive an error when calling it
This is my code of the call
class Pacientes extends React.Component {
state = {
loading: true,
error: null,
data: undefined,
};
componentDidMount() {
this.fetchData();
}
fetchData = async () => {
this.setState({ loading: true, error: null });
try {
const data = await api.pacientes.list();
this.setState({ loading: false, data: data });
} catch (error) {
this.setState({ loading: false, error: error });
}
};
render() {
if (this.state.loading === true && !this.state.data)
return (
<PageLoading/>
);
if (this.state.error) return (
`Este fue el error ${this.state.error}`
);
return (
<React.Fragment>
<TableHeader elementos={this.state.data} />
<Table pacientes={this.state.data} />
</React.Fragment>
);
}
}
And the console says than the error is on the following line :
this.setState({ loading: false, data: data });
But I think than there is not.
Then of make the call of the api i call a component and give props of the answer of the api(Data), and this is the component:
function useSearchPacientes(pacientes) {
const [query, setQuery] = React.useState('');
const [filteredPacientes, setFilteredPacientes] = React.useState(pacientes);
React.useMemo(() => {
const result = pacientes.filter(paciente => {
return (
`${paciente.firstName} ${paciente.lastName}`
)
.toLowerCase()
.includes(query.toLowerCase());
});
setFilteredPacientes(result);
}, [pacientes, query]);
return { query, setQuery, filteredPacientes };
}
function Table(props) {
const pacientes = props.pacientes;
const { query, setQuery, filteredPacientes } = useSearchPacientes(pacientes);
if (filteredPacientes.length === 0) {
return (
"No se encontraron resultados"
);
return (
<React.Fragment>
<div className="search-container">
<form className="search-input-container">
<input type="text" className="search-input form-control" placeholder="Buscar"
value={query}
onChange={(e) => {
setQuery(e.target.value);
}}
/>
<FontAwesomeIcon icon={faSearch} className="text-muted search-input-icon"/>
</form>
<div className="options">
<select name="" className="form-control" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
</div>
</div>
<br />
<div className="row justify-content-center">
<div className="col-10 table-container border-primary">
<br />
<table className="table rounded table-responsive-md">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Nombre</th>
<th scope="col">Apellido</th>
<th scope="col">Twitter</th>
<th scope="col" className="text-center">
Opciones
</th>
</tr>
</thead>
<tbody>
{filteredPacientes.map(paciente => {
return (
<tr key={paciente.id}>
<TableRow paciente={paciente} />
</tr>
);
})}
</tbody>
</table>
</div>
</div>
<br />
</React.Fragment>
);
}
}
So, then of serch this error, i cant found a real solution, but i really think than the error is in the second component, near of the map function to the array.
You have wrongly used closing curly bracket for your if condition
function Table(props) {
const pacientes = props.pacientes;
const { query, setQuery, filteredPacientes } = useSearchPacientes(pacientes);
if (filteredPacientes.length === 0) {
return (
"No se encontraron resultados"
);
} // the closing bracket should be here
return (
<React.Fragment>
<div className="search-container">
<form className="search-input-container">
<input type="text" className="search-input form-control" placeholder="Buscar"
value={query}
onChange={(e) => {
setQuery(e.target.value);
}}
/>
<FontAwesomeIcon icon={faSearch} className="text-muted search-input-icon"/>
</form>
<div className="options">
<select name="" className="form-control" id="">
<option value=""></option>
<option value=""></option>
<option value=""></option>
</select>
</div>
</div>
<br />
<div className="row justify-content-center">
<div className="col-10 table-container border-primary">
<br />
<table className="table rounded table-responsive-md">
<thead>
<tr>
<th scope="col">Id</th>
<th scope="col">Nombre</th>
<th scope="col">Apellido</th>
<th scope="col">Twitter</th>
<th scope="col" className="text-center">
Opciones
</th>
</tr>
</thead>
<tbody>
{filteredPacientes.map(paciente => {
return (
<tr key={paciente.id}>
<TableRow paciente={paciente} />
</tr>
);
})}
</tbody>
</table>
</div>
</div>
<br />
</React.Fragment>
);
}

Categories