The table row cannot be deleted - javascript

I am new to react. I have difficulty deleting the table row. I find that the data variable in the member.js does not show the date that I input that I submitted. Why is that so? Can anyone find a solution why I can't delete the rows that I added.
My App.css
import dataMovielist from '../src/data/data.json';
import Members from './Members';
import AddMember from './AddMember';
import {useState} from 'react';
function App() {
const [datalist, setdatalist] = useState(dataMovielist);
const onSubmitHandler = ((newHobbies)=>{
setdatalist((oldHobbies)=>[newHobbies,...oldHobbies])
})
return (
<div className="App">
<AddMember onSubmitHandler = {onSubmitHandler} />
<Members data={datalist} onSubmitHandler = {onSubmitHandler}/>
</div>
);
}
export default App;
My Member.js
import React, { useState } from "react";
import '../src/css/movie.css'
import moviesdata from '../src/data/data.json';
function Members({ data, onSubmitHandler }) {
const [moviesData, setMoviesData] = useState(data);
console.log(moviesData)
const deleteMoviesHandler = (personIndex) => {
alert("hi")
console.log(moviesData)
moviesData.splice(personIndex, 1);
setMoviesData([...moviesData]);
};
const tableRows = (data) =>
data.map((info, num) => {
return (
<tr key={info.id} >
<td>{info.id}</td>
<td>{info.name}</td>
<td>
<img src={info["picture of image"]} alt=""></img>
</td>
<td>{info["lead actor"]}</td>
<td>{info.rating}</td>
<td><button onClick={()=>deleteMoviesHandler(num)}>Delete</button></td>
</tr>
);
});
return (
<div>
<table className="table table-stripped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Image</th>
<th>Actors</th>
<th>Rating</th>
</tr>
</thead>
<tbody>{tableRows(data)}</tbody>
</table>
</div>
);
}
export default Members;
My addMember.js
import React, { useState } from "react";
import "../src/css/addMember.css";
const AddMember = ({onSubmitHandler}) => {
const [idmovie,setidmovie] = useState("");
const [nameofmovie, setnameofmovie] = useState("");
const [moviepic, setmoviepic] = useState("");
const [leadActor, setleadActor] = useState("");
const [rating, setRating] = useState("");
function onChangeId(event){
setidmovie(event.target.value);
}
function onChangeName(event) {
setnameofmovie(event.target.value);
}
function onChangeImage(event) {
setmoviepic(event.target.value);
}
function onChangeActor(event) {
setleadActor(event.target.value.split(","));
}
function onChangeRating(event) {
setRating(event.target.value);
}
const transferValue = (event) => {
event.preventDefault();
const val = {
id : idmovie,
name: nameofmovie,
"picture of image": moviepic,
"lead actor": leadActor,
rating: rating,
};
onSubmitHandler(val);
clearState();
};
const clearState = () => {
setidmovie("");
setnameofmovie("");
setmoviepic("");
setleadActor("");
setRating("");
};
return (
<div>
<div id="topFormLayerOne">
<form>
<div id="secondFormLayerTwo">
<label id="labelTwo">Please key in the Id</label>
<input
id="inputThree"
type="text"
maxLength="10"
onChange={onChangeId}
placeholder="Please key in the Id"
></input>
<label id="labelFour">Movie Names</label>
<input
onChange={onChangeName}
id="inputFour"
type="text"
maxLength="100"
placeholder="Movies Names"
name="moviesName"
></input>
<label id="labelFive">Picture of Movies</label>
<input
onChange={onChangeImage}
id="inputFive"
type="file"
maxLength="100"
placeholder="Name of Images"
name="imageName"
></input>
<label id="labelSix">Lead Actor Names</label>
<input
onChange={onChangeActor}
id="inputSix"
type="text"
maxLength="500"
placeholder="Name of Actor"
name="actorName"
></input>
<label id="labelSeven">Rating</label>
<input
onChange={onChangeRating}
id="inputSeven"
type="text"
maxLength="10"
placeholder="Rating"
name="movieRating"
></input>
<button onClick={transferValue} id="submitButton">
Submit
</button>
<button id="removeButton">Remove Movie</button>
</div>
</form>
</div>
</div>
);
};
export default AddMember;
My data.json
[{ "id": 1,"name" : "Ticket to Paradise","picture of image":"../images/Ticket_to_Paradise.jpg", "lead actor": ["George Clooney", "Julia Roberts"],"rating":5}]
Can you help me solve theis problems?

Problem
Your deleteMoviesHandler deletes items from their local state of Members and what is rendered is the parent state.
Solution
You don't need to keep another state inside the Members component.
Move the deleteMoviesHandler to the parent component and pass it down to Members.
function App() {
...
...
const deleteMoviesHandler = (personIndex) => {
datalist.splice(personIndex, 1);
setdatalist([...datalist]);
};
...
...
<Members
...
...
deleteMoviesHandler={deleteMoviesHandler}
/>
Use it from Members component.
function Members({ data, onSubmitHandler, deleteMoviesHandler }) {...}
Working Demo:

Related

Next.js trying to push data from input value into json, but onSubmit doesn't work at all

I'm trying to put input value into json file, but submit button doesn't work, can you help me with it?
import PcosData from "/data/pcos.json";
import {useEffect} from "react";
import { useState } from "react";
export default function adminPcos() {
// const CreateMePanel = () => {
const [title, setTitle] = useState(PcosData["pcos-first"].title);
const [time, setTime] = useState(PcosData["pcos-first"].time);
const handleSubmit = (e) => {
PcosData["pcos-first"].title = title;
PcosData["pcos-first"].time = time;
}
return (
<div>
<h1>hello world</h1>
{PcosData["pcos-first"].map((pcosdata) => (
<form onSubmit={handleSubmit} key={ pcosdata.id } method="post">
<input type="text" name={title} defaultValue={pcosdata.title} onChange={(e) => setTitle({text: e.target.value})}/>
<input type="text" name={time} defaultValue={pcosdata.time} onChange={(e) => setTime({text: e.target.value})}/>
<input type="submit" value="submit"/>
</form>
))}
</div>
)
}
i checked all of the functions, variables, but didn't find any errors

React Props.func is not a working for React

I am new to react. I find this problem when I run the react program. Its say "props.func is not a function"
My AddMembers.js
import React, { useState } from "react";
import { useNavigate } from "react-router-dom
import "../src/css/AddMember.css";
import '../src/data/data.json';
Part of the code of AddMember.js
const AddMember = (props) => {
let movies = [];
const navigate = useNavigate();
const [nameofmovie, setnameofmovie] = useSt
const [moviepic,setmoviepic] = useState("")
const [leadActor,setleadActor] = useState("
const [rating,setRating] = useState("");
function onChangeName(event) {
setnameofmovie(event.target.value);
}
function onChangeImage(event){
setmoviepic(event.target.value);
}
function onChangeActor(event){
setleadActor(event.target.value.split(",")
}
function onChangeRating(event){
setRating(event.target.value);
}
const transferValue = (event) => {
console.log('props obj:', props)
event.preventDefault();
const val = {
"name" :nameofmovie,
"picture of image": moviepic,
"lead actor": leadActor,
"rating": rating
};
props.func(val);
clearState();
navigate("/members");
};
const clearState = () => {
setnameofmovie(' ');
setmoviepic(' ');
setleadActor(' ')
setRating(' ');
};
return (
<div>
<div id="topFormLayerOne" >
<form>
<div id="secondFormLayerTwo">
<label id="labelFour">Movie Names
<input
onChange={onChangeName}
id="inputFour"
type="text"
maxLength="100"
placeholder="Movies Names"
name="moviesName"
></input>
<label id="labelFive">Picture of
<input
onChange={onChangeImage}
id="inputFive"
type="file"
maxLength="100"
placeholder="Name of Images"
name="imageName"
></input>
<label id="labelSix">Lead Actor N
<input
onChange={onChangeActor}
id="inputSix"
type="text"
maxLength="500"
placeholder="Name of Actor"
name="actorName"
></input>
<label id="labelSeven">Rating</la
<input
onChange={onChangeRating}
id="inputSeven"
type="text"
maxLength="10"
placeholder="Rating"
name="movieRating"
></input>
<button onClick={transferValue} i
<button id="removeButton">Remove
</div>
</form>
</div>
<p>{movies}</p>
</div>
);
};
export default AddMember;
My Members.js.
import React, { useState } from "react";
import jsonData from "../src/data/data.json";
import AddMember from "./AddMember";
function Members() {
const [studentData, setStudentData] = useState(jsonData);
const tableRows = studentData.map((info) => {
return (
<tr key={info.id}>
<td>{info.id}</td>
<td>{info.name}</td>
<td><img src={info["picture of image"]} alt=""></img></td>
<td>
{info["lead actor"]}
</td>
<td>{info. Rating}</td>
</tr>
);
})
const addRows = (data) => {
const totalStudents = studentData.length;
data.id = totalStudents + 1;
const updatedStudentData = [...studentData];
updatedStudentData.push(data);
setStudentData(updatedStudentData);
};
return (
<div>
<table className="table table-stripped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Image</th>
<th>Actors</th>
<th>Rating</th>
</tr>
</thead>
<tbody>{tableRows}</tbody>
</table>
<AddMember func={()=>addRows()} />
</div>
);
}
export default Members;
This is the json data file
[{ "id": 1,"name" : "Ticket to Paradise","picture of image":"../images/Ticket_to_Paradise.jpg", "lead actor": ["George Clooney, Julia Roberts"],"rating":5}]
If I don't add the navigate(), everything is working fine. But once I add the navigate, the error "Uncaught TypeError: props.func is not a function" occurs. The image also cannot work
How i am going to define image in json?
THe AddMember.js
import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import "../src/css/AddMember.css";
import '../src/data/data.json';
const AddMember = (props) => {
let movies = [];
const navigate = useNavigate();
const [nameofmovie, setnameofmovie] = useState("");
const [moviepic,setmoviepic] = useState("");
const [leadActor,setleadActor] = useState("");
const [rating,setRating] = useState("");
function onChangeName(event) {
setnameofmovie(event.target.value);
}
function onChangeImage(event){
setmoviepic(event.target.value);
}
function onChangeActor(event){
setleadActor(event.target.value.split(","))
}
function onChangeRating(event){
setRating(event.target.value);
}
const transferValue = (event) => {
console.log('props obj:', props)
event.preventDefault();
const val = {
"name" :nameofmovie,
"picture of image": moviepic,
"lead actor": leadActor,
"rating":rating
};
props.func(val);
clearState();
navigate("/members");
};
const clearState = () => {
setnameofmovie(' ');
setmoviepic(' ');
setleadActor(' ')
setRating(' ');
};
return (
<div>
<div id="topFormLayerOne" >
<form>
<div id="secondFormLayerTwo">
<label id="labelFour">Movie Names</label>
<input
onChange={onChangeName}
id="inputFour"
type="text"
maxLength="100"
placeholder="Movies Names"
name="moviesName"
></input>
<label id="labelFive">Picture of Movies</label>
<input
onChange={onChangeImage}
id="inputFive"
type="file"
maxLength="100"
placeholder="Name of Images"
name="imageName"
></input>
<label id="labelSix">Lead Actor Names</label>
<input
onChange={onChangeActor}
id="inputSix"
type="text"
maxLength="500"
placeholder="Name of Actor"
name="actorName"
></input>
<label id="labelSeven">Rating</label>
<input
onChange={onChangeRating}
id="inputSeven"
type="text"
maxLength="10"
placeholder="Rating"
name="movieRating"
></input>
<button onClick={transferValue} id="submitButton">Submit</butto
<button id="removeButton">Remove Movie</button>
</div>
</form>
</div>
<p>{movies}</p>
</div>
);
};
export default AddMember;
the Member.js
import React, { useState } from "react";
import jsonData from "../src/data/data.json";
import AddMember from "./AddMember";
function Members() {
const [studentData, setStudentData] = useState(jsonData);
const tableRows = studentData.map((info) => {
return (
<tr key={info.id}>
<td>{info.id}</td>
<td>{info.name}</td>
<td><img src={info["picture of image"]} alt=""></img></td>
<td>
{info["lead actor"]}
</td>
<td>{info.rating}</td>
</tr>
);
})
const addRows = (data) => {
const totalStudents = studentData.length;
data.id = totalStudents + 1;
const updatedStudentData = [...studentData];
updatedStudentData.push(data);
setStudentData(updatedStudentData);
};
return (
<div>
<table className="table table-stripped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Image</th>
<th>Actors</th>
<th>Rating</th>
</tr>
</thead>
<tbody>{tableRows}</tbody>
</table>
<AddMember func={()=>addRows()} />
</div>
);
}
export default Members;
Here I rewrite the Member.js and AddMember.js.

Need to Pass props to other components in hook

i want to pass a prop from one(App.jsx) component to other component(form.jsx) in state hooks
App.jsx
import React, {useEffect, useState} from 'react';
import Form from './components/Form';
import Table from './components/Table';
import axios from 'axios';
const App = () => {
const [data, setData] = useState({data:[]});
const [editData, setEditData] = useState([]);
const create = (data) => {
axios.post('http://localhost:5000/info',data).then((res) =>{
getAll();
})
}
useEffect(() =>{
getAll();
},[])
const getAll = () =>{
axios.get("http://localhost:5000/info").then((response) =>{
setData({
data:response.data
})
})
}
const update = event =>{
setEditData(data)
console.log(data); // THIS "data" is the prop that i need to pass to Form.jsx component
}
return (
<div>
<div>
<Form myData={create} editForm={editData} />
</div>
<div>
<Table getData={data} edit={update} />
</div>
</div>
);
};
export default App;
i want that "data" value form App.jsx component as props in this Form.jsx component
Form.jsx
import React, {useState} from 'react';
const Form = (props) => {
const [formData, setFormData] = useState({ Name:'', Age:'', City:''});
const infoChange = e => {
const { name,value} = e.target;
setFormData({
...formData,
[name]: value,
})
}
const infoSubmit = e =>{
e.preventDefault();
let data={
Name:formData.Name,
Age:formData.Age,
City:formData.City
}
props.myData(data);
}
const componentWillReceive = (props) => { // i want the props data here
console.log(props.data); // in class component they use componentWillReceiveRrops ,
} // is there any alternative for function based component to receive props?
return (
<div>
<form onSubmit={infoSubmit} autoComplete="off">
<div>
<label>Name:</label>
<input type="text" onChange={infoChange} name="Name" value={formData.Name} placeholder="Enter Name" />
</div>
<div>
<label>City:</label>
<input type="text" onChange={infoChange} name="City" value={formData.City}
placeholder="Enter City" />
</div>
<div>
<label>Age:</label>
<input type="text" onChange={infoChange} name="Age" value={formData.Age} placeholder="Enter Age" />
</div>
<button type="submit">Submit</button>
</form>
</div>
);
};
export default Form;
i have commented the area of problem within the code , you can ignore the return () block of code.
Sorry for silly questions but THANKYOU Very Much !!! in advance
Use the following code in Form.jsx, the useEffect will listen the change of props.data and update the value
useEffect(() => {
setFormData(props.data);
},
[props.data]);
For more information, you may check the following answer
https://stackoverflow.com/a/65842783/14674139

UI doesn't update in react js using redux toolkit + inputs error

I know this is common question and something is wrong with state, but I still need help with understanding of all features of Redux and Redux-toolkit. So, in my PET project I'm trying to edit an invoice, but UI isn't updating, however it logs to the console changes which you make (here is screenshot).
And if I try to edit items(item name or unit costs or unit) it shows an error.
It's kind of 2 problems in one post, but related to the same topic :)
Now the code.
invoice-slice.js file with editInvoice reducer where might be the problem of updating the state, but i don't know where it can be:
editInvoice(state) {
const existingItem = state.invoices;
existingItem.map((item) => {
if (existingItem.id === item.id) {
return {
id: item.id,
bill_from: item.billFrom,
bill_from_info: item.billFromInfo,
bill_to: item.billTo,
bill_to_info: item.billToInfo,
invoice_num: item.invoiceNumber,
status: item.status,
order_date: item.order_date,
ITEMS: [...item.ITEMS],
};
}
return item;
});
},
EditInvoice.js file:
import React from "react";
import { useParams } from "react-router-dom";
import { useSelector } from "react-redux";
import classes from "./EditInvoice.module.css";
import EditInvoiceItem from "./EditInvoiceItem";
const EditInvoice = () => {
const { invoiceId } = useParams();
const invoices = useSelector((state) => state.invoice.invoices);
const invoice = invoices.find((invoice) => invoice.id === invoiceId);
return invoice ? (
<EditInvoiceItem
invoiceNumber={invoice.invoice_num}
billFrom={invoice.bill_from}
billFromInfo={invoice.bill_from_info}
billTo={invoice.bill_to}
billToInfo={invoice.bill_to_info}
status={invoice.status}
orderDate={invoice.order_date}
items={invoice.ITEMS}
itemName={invoice.item_name}
unitCosts={invoice.unit_costs}
units={invoice.units}
/>
) : (
<div className={classes.centered}>Invoice Not Found.</div>
);
};
export default EditInvoice;
EditInvoiceItem.js file:
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { uiActions } from "../../store/ui-slice";
import classes from "./AddInvoiceItem.module.css";
import { useFormik } from "formik";
import Wrapper from "../../UI/Wrapper";
import Card from "../../UI/Card";
import Footer from "../../UI/Footer";
import Button from "../../UI/Button";
import DatePicker from "react-datepicker";
import "react-datepicker/dist/react-datepicker.css";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import { faCalendar } from "#fortawesome/free-solid-svg-icons";
import { faEllipsis } from "#fortawesome/free-solid-svg-icons";
import { invoiceActions } from "../../store/invoice-slice";
import { useNavigate } from "react-router-dom";
const EditInvoiceItem = (props) => {
const navigate = useNavigate();
const date = new Date();
const options = ["Pending", "Shipped", "Delivered"];
const inputs = [{ item_name: "", unit_costs: "", unit: "" }];
const [startDate, setStartDate] = useState(date);
// const [startDate, setStartDate] = useState(props.orderDate || date);
const [selectedOption, setSelectedOption] = useState(
props.status || options[0]
);
const [listItems, setListItems] = useState(props.items || inputs);
// console.log(props.orderDate.toJSON());
const optionClickHandler = (value) => () => {
setSelectedOption(value);
dispatch(uiActions.toggleMoreOptions());
};
const editInvoiceHandler = (invoice) => {
console.log(invoice);
dispatch(
invoiceActions.editInvoice({
id: invoice.id,
invoiceNumber: invoice.invoiceNumber,
billFrom: invoice.billFrom,
billFromInfo: invoice.billFromInfo,
billTo: invoice.billTo,
billToInfo: invoice.billToInfo,
status: selectedOption,
order_date: startDate.toLocaleDateString(),
ITEMS: [...updateValuesOnSubmit()],
})
);
};
const formikEditInvoice = useFormik({
initialValues: {
invoiceNumber: props.invoiceNumber,
billFrom: props.billFrom,
billFromInfo: props.billFromInfo,
billTo: props.billTo,
billToInfo: props.billToInfo,
status: props.status,
order_date: props.orderDate,
item_name: props.itemName,
unit_costs: props.unitCosts,
units: props.units,
},
onSubmit: (val) => {
editInvoiceHandler(val);
navigate("/invoices", { replace: true });
},
});
const dispatch = useDispatch();
const toggleMoreOptions = () => {
dispatch(uiActions.toggleMoreOptions());
};
const showOtherOptions = useSelector(
(state) => state.ui.selectMoreOptionsIsVisible
);
let counter = 1;
const addItemHandler = () => {
setListItems(listItems.concat({ item_name: "", unit_costs: "", unit: "" }));
};
const updateItemHandler = (index, inputName, value) => {
listItems[index] = { ...listItems[index], [inputName]: value };
};
const updateValuesOnSubmit = () => {
return listItems;
};
const navigateBack = () => {
navigate(-1);
};
return (
<form onSubmit={formikEditInvoice.handleSubmit}>
<Wrapper isShrinked={props.isShrinked}>
<Card>
<div className={classes.content}>
<div className={classes["buttons-wrapper"]}>
<button
type="button"
className={classes["cancel-btn"]}
onClick={navigateBack}
>
Cancel
</button>
<Button>Save</Button>
</div>
<div className={classes["invoice-info-wrapper"]}>
<div className={classes["invoice-info"]}>
<h3>Invoice Info</h3>
<input
placeholder="Number"
type="text"
name="invoiceNumber"
id="invoiceNumber"
onChange={formikEditInvoice.handleChange}
value={formikEditInvoice.values.invoiceNumber}
onBlur={formikEditInvoice.handleBlur}
></input>
</div>
<div className={classes["right-side-column"]}>
<div className={classes["order-status"]}>
<span>Order Status: </span>
<div className={classes.buttons}>
{showOtherOptions && (
<ul className={classes.options}>
{options.map((option, index) => (
<li onClick={optionClickHandler(option)} key={index}>
{option}
</li>
))}
</ul>
)}
<button type="button" className={classes.status}>
{selectedOption}
</button>
<button
type="button"
className={classes.dots}
onClick={toggleMoreOptions}
>
<FontAwesomeIcon icon={faEllipsis} />
</button>
</div>
</div>
<div className={classes["order-date"]}>
<span>Order Date:</span>
<DatePicker
className={classes["order-date-input"]}
selected={startDate}
onChange={(val) => setStartDate(val)}
/>
<FontAwesomeIcon
icon={faCalendar}
className={classes.calendar}
></FontAwesomeIcon>
</div>
</div>
</div>
<div className={classes["order-bills"]}>
<div className={classes["bill-from"]}>
<input
placeholder="Bill From"
type="text"
name="billFrom"
id="billFrom"
onChange={formikEditInvoice.handleChange}
value={formikEditInvoice.values.billFrom}
onBlur={formikEditInvoice.handleBlur}
></input>
<textarea
placeholder="Bill From Info"
name="billFromInfo"
id="billFromInfo"
onChange={formikEditInvoice.handleChange}
value={formikEditInvoice.values.billFromInfo}
onBlur={formikEditInvoice.handleBlur}
></textarea>
</div>
<div className={classes["bill-to"]}>
<input
placeholder="Bill To"
type="text"
name="billTo"
id="billTo"
onChange={formikEditInvoice.handleChange}
value={formikEditInvoice.values.billTo}
onBlur={formikEditInvoice.handleBlur}
></input>
<textarea
placeholder="Bill To Info"
name="billToInfo"
id="billToInfo"
onChange={formikEditInvoice.handleChange}
value={formikEditInvoice.values.billToInfo}
onBlur={formikEditInvoice.handleBlur}
></textarea>
</div>
</div>
<div className={classes["table-wrapper"]}>
<table>
<colgroup>
<col className={classes.col1}></col>
<col className={classes.col2}></col>
<col className={classes.col3}></col>
<col className={classes.col4}></col>
<col className={classes.col5}></col>
<col className={classes.col6}></col>
</colgroup>
<thead>
<tr>
<td className={classes["more-padding"]}>#</td>
<td>Item Name</td>
<td>Unit Costs</td>
<td>Unit</td>
<td>Price</td>
<td></td>
</tr>
</thead>
<tbody>
{listItems.map((item, index) => (
<tr data-1={item} key={index}>
<td className={classes["more-padding"]}>{counter++}</td>
<td>
<input
placeholder="Item Name"
className={classes.inputs}
name="itemName"
id="itemName"
onChange={(e) =>
updateItemHandler(
index,
"item_name",
e.currentTarget.value
)
}
value={item.item_name}
onBlur={formikEditInvoice.handleBlur}
></input>
</td>
<td>
<input
placeholder="Unit Costs"
className={classes.inputs}
name="unitCosts"
id="unitCosts"
onChange={(e) =>
updateItemHandler(
index,
"unit_costs",
e.currentTarget.value
)
}
value={item.unit_costs}
onBlur={formikEditInvoice.handleBlur}
></input>
</td>
<td>
<input
placeholder="Unit"
className={classes.inputs}
name="unit"
id="unit"
onChange={(e) =>
updateItemHandler(
index,
"unit",
e.currentTarget.value
)
}
value={item.unit}
onBlur={formikEditInvoice.handleBlur}
></input>
</td>
<td>0</td>
<td></td>
{/* There should be dynamic values later */}
</tr>
))}
</tbody>
</table>
<div className={classes["add-item-btn"]}>
<button
onClick={addItemHandler}
type="button"
className={classes["add-item-btn"]}
>
Add Item
</button>
</div>
<div className={classes.total}>
<p className={classes["sub-total"]}>
<span>Sub Total: </span>
<span>$0</span>
{/* Dynamic value later here */}
</p>
<div className={classes["total-vat"]}>
<span>Total Vat:</span>
<div className={classes["total-sum"]}>
<span className={classes["input-wrapper"]}>
<input type="text" defaultValue="10"></input>
<span>%</span>
</span>
<span className={classes.sum}>$0</span>
{/* Dynamic value later here */}
</div>
</div>
<div className={classes["grand-total"]}>
<h3>Grand Total</h3>
<div className={classes.input}>
<input type="text" defaultValue="$"></input>
<span>0</span>
{/* Dynamic value later here */}
</div>
</div>
</div>
</div>
<div className={classes.dummy}></div>
</div>
</Card>
<Footer />
</Wrapper>
</form>
);
};
export default EditInvoiceItem;
In my project I'm using Formik to listen for input changes, but in listening to items changes I'm not using it, because i had an issue with that and one guy suggested me that code.
So, I'm facing 2 issues:
UI doesn't update the changes, but i can see in console that changes are made(probably the code in invoice-slice.js is wrong);
When i click and want to change the inputs of Item Name, Unit Costs and Unit i get an error in console and can't change anything.
Please, try helping me and explaining what can cause such problems!
P.S. here is my github repo - https://github.com/stepan-slyvka/test-project
P.P.S. and here is CodeSandbox -
Issues
The main issue is that the editInvoice reducer function isn't consuming an action and its payload, so the passed updated invoice data isn't referenced, and the array mapping result isn't used.
Additionally, the EditInvoice component isn't passing along the invoice id to the EditInvoiceItem (*or EditInvoiceItem isn't capturing it from the path parameters. The invoice.id isn't populated into the form data so it's also not passed along to editInvoiceHandler to be dispatched to the store. This causes the array mapping to fail to find the invoice object that needs to be updated.
Solution
EditInvoice
EditInvoice needs to pass invoice.id as a prop to EditInvoiceItem. It would be quite a bit more clean and easier to maintain to simply pass the entire invoice object though.
const EditInvoice = () => {
const { invoiceId } = useParams();
const invoices = useSelector((state) => state.invoice.invoices);
const invoice = invoices.find((invoice) => invoice.id === invoiceId);
return invoice ? (
<EditInvoiceItem
id={invoice.id} // <-- passed here
invoiceNumber={invoice.invoice_num}
billFrom={invoice.bill_from}
billFromInfo={invoice.bill_from_info}
billTo={invoice.bill_to}
billToInfo={invoice.bill_to_info}
status={invoice.status}
orderDate={invoice.order_date}
items={invoice.ITEMS}
itemName={invoice.item_name}
unitCosts={invoice.unit_costs}
units={invoice.units}
/>
) : (
<div className={classes.centered}>Invoice Not Found.</div>
);
};
EditInvoiceItem
EditInvoiceItem should initialize the form state with the invoice id.
const formikEditInvoice = useFormik({
initialValues: {
id: props.id, // <-- pass id value...
invoiceNumber: props.invoiceNumber,
billFrom: props.billFrom,
billFromInfo: props.billFromInfo,
billTo: props.billTo,
billToInfo: props.billToInfo,
status: props.status,
order_date: props.orderDate,
item_name: props.itemName,
unit_costs: props.unitCosts,
units: props.units,
},
onSubmit: (val) => {
editInvoiceHandler(val); // <-- ...so it's passed along here
navigate("/invoices", { replace: true });
},
});
invoice-slice
The editInvoice case reducer should consume both the current state and the dispatched action so the payload containing the invoice data can be accessed.
editInvoice(state, action) {
const { payload } = action;
state.invoices = state.invoices.map((item) =>
item.id === payload.id
? {
...item,
bill_from: payload.billFrom,
bill_from_info: payload.billFromInfo,
bill_to: payload.billTo,
bill_to_info: payload.billToInfo,
invoice_num: payload.invoiceNumber,
status: payload.status,
order_date: payload.order_date,
ITEMS: payload.ITEMS.slice()
}
: item
);
}

Why is my boolean statement always evaluating to true?

I'm pretty new to javascript, and I am trying to figure out how to calculate sales tax based off of US states. In my code, I attempted to use an if else statement based off of the input value of state to accomplish this. However, no matter what I put in for the value of state the tax is determined based off of 8.75%, and I'm not sure what I am doing wrong. I would really appreciate any help or advice on how to fix this problem.
Thank you
PlaceOrderScreen.js
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import { createOrder } from '../actions/orderActions';
import CheckoutSteps from '../components/CheckoutSteps';
import { ORDER_CREATE_RESET } from '../constants/orderConstants';
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';
export default function PlaceOrderScreen(props) {
const cart = useSelector((state) => state.cart);
if (!cart.paymentMethod) {
props.history.push('/payment');
}
const orderCreate = useSelector((state) => state.orderCreate);
const { loading, success, error, order } = orderCreate;
const toPrice = (num) => Number(num.toFixed(2)); // 5.123 => "5.12" => 5.12
cart.itemsPrice = toPrice(
cart.cartItems.reduce((a, c) => a + c.qty * c.price, 0)
);
//Sales Tax//
{
if (cart.shippingAddress.state === 'New York'||'NY'){
cart.taxPrice = toPrice(0.0875 * cart.itemsPrice)}
else if (cart.shippingAddress.state === 'Kansas'||'KS') {
cart.taxPrice = toPrice(0.065 * cart.itemsPrice)}
else {
cart.taxPrice = toPrice(0 * cart.itemsPrice)}
};
cart.totalPrice = cart.itemsPrice + cart.shippingPrice + cart.taxPrice;
const dispatch = useDispatch();
const placeOrderHandler = () => {
dispatch(createOrder({ ...cart, orderItems: cart.cartItems }));
};
useEffect(() => {
if (success) {
props.history.push(`/order/${order._id}`);
dispatch({ type: ORDER_CREATE_RESET });
}
}, [dispatch, order, props.history, success]);
return (
<div>
<CheckoutSteps step1 step2 step3 step4></CheckoutSteps>
<div className="row top">
<div className="col-2">
<ul>
<li>
<div className="card card-body">
<h2>Shipping</h2>
<p>
<strong>Name:</strong> {cart.shippingAddress.fullName} <br />
<strong>Address: </strong> {cart.shippingAddress.address},
{cart.shippingAddress.city}, {cart.shippingAddress.state}, {cart.shippingAddress.postalCode}
,{cart.shippingAddress.country}
</p>
</div>
</li>
</ul>
</div>
</div>
</div>
ShippingAddressScreen.js
import React, { useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { saveShippingAddress } from '../actions/cartActions';
import CheckoutSteps from '../components/CheckoutSteps';
export default function ShippingAddressScreen(props) {
const userSignin = useSelector((state) => state.userSignin);
const { userInfo } = userSignin;
const cart = useSelector((state) => state.cart);
const { shippingAddress } = cart;
if (!userInfo) {
props.history.push('/signin');
}
const [fullName, setFullName] = useState(shippingAddress.fullName);
const [address, setAddress] = useState(shippingAddress.address);
const [city, setCity] = useState(shippingAddress.city);
const [state, setState] = useState(shippingAddress.state);
const [postalCode, setPostalCode] = useState(shippingAddress.postalCode);
const [country, setCountry] = useState(shippingAddress.country);
const dispatch = useDispatch();
const submitHandler = (e) => {
e.preventDefault();
dispatch(
saveShippingAddress({ fullName, address, city, state, postalCode, country })
);
props.history.push('/payment');
};
return (
<div>
<CheckoutSteps step1 step2></CheckoutSteps>
<form className="form" onSubmit={submitHandler}>
<div>
<h1>Shipping Address</h1>
</div>
<div>
<label htmlFor="fullName">Full Name</label>
<input
type="text"
id="fullName"
placeholder="Enter full name"
value={fullName}
onChange={(e) => setFullName(e.target.value)}
required
></input>
</div>
<div>
<label htmlFor="address">Address</label>
<input
type="text"
id="address"
placeholder="Enter address"
value={address}
onChange={(e) => setAddress(e.target.value)}
required
></input>
</div>
<div>
<label htmlFor="city">City</label>
<input
type="text"
id="city"
placeholder="Enter city"
value={city}
onChange={(e) => setCity(e.target.value)}
required
></input>
</div>
<div>
<label htmlFor="state">State</label>
<input
type="text"
id="state"
placeholder="Enter state"
value={state}
onChange={(e) => setState(e.target.value)}
required
></input>
</div>
<div>
<label htmlFor="postalCode">Postal Code</label>
<input
type="text"
id="postalCode"
placeholder="Enter postal code"
value={postalCode}
onChange={(e) => setPostalCode(e.target.value)}
required
></input>
</div>
<div>
<label htmlFor="country">Country</label>
<input
type="text"
id="country"
placeholder="Enter country"
value={country}
onChange={(e) => setCountry(e.target.value)}
required
></input>
</div>
<div>
<label />
<button className="primary" type="submit">
Continue
</button>
</div>
</form>
</div>
);
}
Your code should look like this:
cart.shippingAddress.state === 'New York'|| cart.shippingAddress.state === 'NY'
Your current code is testing if the string "NY" is true or not, and that evaluates to true in your boolean test, so you're always getting the 8.75% tax rate.

Categories

Resources