I'm trying to convert the class components in my Reactjs ToDo app to functional components. Here is one of the my original components:
import React, { Component } from "react";
import TaskDataService from "../services/task.service";
import FadeIn from 'react-fade-in';
import { Link } from "react-router-dom";
export default class TasksList extends Component {
constructor(props) {
super(props);
this.onChangeSearchTitle = this.onChangeSearchTitle.bind(this);
this.retrieveTasks = this.retrieveTasks.bind(this);
this.refreshList = this.refreshList.bind(this);
this.setActiveTask = this.setActiveTask.bind(this);
this.removeAllTasks = this.removeAllTasks.bind(this);
this.searchTitle = this.searchTitle.bind(this);
this.state = {
Tasks: [],
currentTask: null,
currentIndex: -1,
searchTitle: ""
};
}
componentDidMount() {
this.retrieveTasks();
}
onChangeSearchTitle(e) {
const searchTitle = e.target.value;
this.setState({
searchTitle: searchTitle
});
}
retrieveTasks() {
TaskDataService.getAll()
.then(response => {
this.setState({
Tasks: response.data
});
console.log(response.data);
})
.catch(e => {
console.log(e);
});
}
refreshList() {
this.retrieveTasks();
this.setState({
currentTask: null,
currentIndex: -1
});
}
setActiveTask(Task, index) {
this.setState({
currentTask: Task,
currentIndex: index
});
}
removeAllTasks() {
TaskDataService.deleteAll()
.then(response => {
console.log(response.data);
this.refreshList();
})
.catch(e => {
console.log(e);
});
}
searchTitle() {
this.setState({
currentTask: null,
currentIndex: -1
});
TaskDataService.findByTitle(this.state.searchTitle)
.then(response => {
this.setState({
Tasks: response.data
});
console.log(response.data);
})
.catch(e => {
console.log(e);
});
}
render() {
const { searchTitle, Tasks, currentTask, currentIndex } = this.state;
return (
<FadeIn>
<div className="list row">
<div className="col-md-8">
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="Search by title"
value={searchTitle}
onChange={this.onChangeSearchTitle}
/>
<div className="input-group-append">
<button
className="btn btn-outline-secondary"
type="button"
onClick={this.searchTitle}
>
Search
</button>
</div>
</div>
</div>
<div className="col-md-6">
<h4>Tasks List</h4>
<FadeIn>
<ul className="list-group">
{Tasks &&
Tasks.map((Task, index) => (
<li
className={
"list-group-item " +
(index === currentIndex ? "active" : "")
}
onClick={() => this.setActiveTask(Task, index)}
key={index}
>
<div className="align-left">
{Task.title}
</div>
<div className="align-right">
{Task.startDate.toString().split("T")[0]}
</div>
</li>
))}
</ul>
</FadeIn>
<button
className="m-3 btn btn-sm btn-danger"
onClick={this.removeAllTasks}
>
Remove All
</button>
</div>
<div className="col-md-6">
{currentTask ? (
<FadeIn>
<div>
<h4>Task</h4>
<div>
<label>
<strong>Title:</strong>
</label>{" "}
{currentTask.title}
</div>
<div>
<label>
<strong>Description:</strong>
</label>{" "}
{currentTask.description}
</div>
<div>
<label>
<strong>Status:</strong>
</label>{" "}
{currentTask.completed ? "Completed" : "Pending"}
</div>
<div>
<label>
<strong>Due Date:</strong>
</label>{" "}
{currentTask.startDate.split("T")[0]}
</div>
<Link
to={"/Tasks/" + currentTask.id}
className="badge badge-warning"
>
Edit
</Link>
</div>
</FadeIn>
) : (
<div>
<br />
<p>Please click on a Task...</p>
</div>
)}
</div>
</div>
</FadeIn>
);
}
}
...and my attempt to convert it into a functional component:
import React, { useState, useEffect } from "react";
import TaskDataService from "../services/task.service";
import FadeIn from 'react-fade-in';
import { Link } from "react-router-dom";
function TasksList() {
const [Tasks, setTasks] = useState([]);
const [currentTask, setCurrentTask] = useState(null);
const [currentIndex, setCurrentIndex] = useState(-1);
const [searchTitle, setSearchTitle] = useState("");
useEffect(() => {
retrieveTasks();
});
const onChangeSearchTitle = (e) => {
const searchTitle = e.target.value;
setSearchTitle({
searchTitle: searchTitle
});
}
const retrieveTasks = () => {
TaskDataService.getAll()
.then(response => {
setTasks({
Tasks: response.data
});
console.log(response.data);
})
.catch(e => {
console.log(e);
});
}
const refreshList = () => {
retrieveTasks();
setTasks(null);
setCurrentIndex(-1);
}
const setActiveTask = (Task, index) => {
setTasks( Task );
setCurrentIndex( index );
}
const removeAllTasks = () => {
TaskDataService.deleteAll()
.then(response => {
console.log(response.data);
refreshList();
})
.catch(e => {
console.log(e);
});
}
const onSearchTitle = () => {
setTasks(null);
setCurrentIndex(-1);
TaskDataService.findByTitle(searchTitle)
.then(response => {
setTasks(response.data)
console.log(response.data);
})
.catch(e => {
console.log(e);
});
}
return (
<FadeIn>
<div className="list row">
<div className="col-md-8">
<div className="input-group mb-3">
<input
type="text"
className="form-control"
placeholder="Search by title"
value={searchTitle}
onChange={onChangeSearchTitle}
/>
<div className="input-group-append">
<button
className="btn btn-outline-secondary"
type="button"
onClick={onSearchTitle}
>
Search
</button>
</div>
</div>
</div>
<div className="col-md-6">
<h4>Tasks List</h4>
<FadeIn>
<ul className="list-group">
{Tasks &&
Tasks.map((Task, index) => (
<li
className={
"list-group-item " +
(index === currentIndex ? "active" : "")
}
onClick={() => setActiveTask(Task, index)}
key={index}
>
<div className="align-left">
{Task.title}
</div>
<div className="align-right">
{Task.startDate.toString().split("T")[0]}
</div>
</li>
))}
</ul>
</FadeIn>
<button
className="m-3 btn btn-sm btn-danger"
onClick={removeAllTasks}
>
Remove All
</button>
</div>
<div className="col-md-6">
{currentTask ? (
<FadeIn>
<div>
<h4>Task</h4>
<div>
<label>
<strong>Title:</strong>
</label>{" "}
{currentTask.title}
</div>
<div>
<label>
<strong>Description:</strong>
</label>{" "}
{currentTask.description}
</div>
<div>
<label>
<strong>Status:</strong>
</label>{" "}
{currentTask.completed ? "Completed" : "Pending"}
</div>
<div>
<label>
<strong>Due Date:</strong>
</label>{" "}
{currentTask.startDate.split("T")[0]}
</div>
<Link
to={"/tasks/" + currentTask.id}
className="badge badge-warning"
>
Edit
</Link>
</div>
</FadeIn>
) : (
<div>
<br />
<p>Please click on a Task...</p>
</div>
)}
</div>
</div>
</FadeIn>
);
}
export default TasksList;
But when running my frontend, the page fails to load with this error seeming like the big one: "Uncaught TypeError: Tasks.map is not a funtion". Console points to this segment as the culprit:
<ul className="list-group">
{Tasks &&
Tasks.map((Task, index) => (
<li...
So it doesn't like Tasks.map. I've spent a lot of time on research and can't figure out what the problem is. Any ideas?
It seems that you are settings in multiple part of your code with setTasks a value other than an array which eventually can leads to Tasks.map triggering an error.
For exemple in the function retreiveTasks you are setting Tasks to an object.
Related
I'm trying to submit reviews to a directus app but the review is not getting added to the data.
I can retrieve the data but cannot add.
I've checked all permissions and set the directus app to public permissions.
cannot figure out what the problem could be.
can anyone advise what could be wrong?
the api call:
import axios from 'axios';
const url = 'https://pwsbbqhj.directus.app/items/Reviews';
export const readReviews = () => axios.get(url);
export const createReview = (newReview) => axios.post(url, newReview);
the data retrieval :
import React, { useState, useEffect } from 'react';
import * as api from '../../../api';
import { FaStar } from 'react-icons/fa';
const colors = {
orange: '#e42320',
grey: '#a9a9a9',
};
function Ratings() {
const stars = Array(5).fill(0);
const [currentValue, setCurrentValue] = React.useState(0);
const [hoverValue, setHoverValue] = React.useState(undefined);
const handleClick = (value) => {
setCurrentValue(value);
};
const handleMouseOver = (value) => {
setHoverValue(value);
};
const [review, setReview] = useState({});
const [reviews, setReviews] = useState([]);
useEffect(() => {
const fetchData = async () => {
const result = await api.readReviews();
setReviews(result.data.data);
};
fetchData();
}, []);
const createReview = async (review) => {
try {
const data = await api.createReview({ review });
setReview([...reviews, data.data]);
} catch (error) {
console.log(error);
}
};
let [reviewCount, setreviewCount] = useState([]);
const setCountFxn = (no) => {
setReview(no);
console.log(no);
};
return (
<div className='col-md-12 row-testimonials'>
<div className='reviews-heading pb-5 pt-5'>
<h2>REVIEWS FROM OUR CUSTOMERS</h2>
</div>
<div
className='themesflat-carousel-box has-bullets bullet-circle has-buttons has-arrows clearfix'
data-gap={30}
data-column={3}
data-column2={2}
data-column3={1}
data-auto='false'
>
<div className='owl-carousel owl-theme'>
{reviews.map((review) => (
<div className='themesflat-testimonials style-2 align-center clearfix' key={review.id}>
<div className='testimonial-item'>
<div className='inner'>
<div className='thumb'>
<img src='assets/img/testimonials/customer-1-90x90.jpg' alt='altimage' />
</div>
<blockquote className='text'>
<div className='name-pos clearfix'>
<h6 className='name'>{review.Title}</h6>
<span className='position'></span>
</div>
<p>{review.Body}</p>
<div className='list-star'>
{Array.from({ length: review.Rating }).map((i) => (
<FaStar key={i} size={18} color={colors.orange} />
))}
</div>
<div className='m-2'>
By: <span className='name'>{review.Name}</span>
</div>
</blockquote>
</div>
</div>
</div>
))}
</div>
</div>
<div className='bg-black'>
<form>
<div className='mb-5'>
<h2>RATE OUR SERVICE</h2>
<div className='mt-5 mb-5'>
{stars.map((_, index) => {
return (
<FaStar
key={index}
size={20}
style={{
marginRight: 10,
cursor: 'pointer',
}}
color={(hoverValue || currentValue) > index ? colors.orange : colors.grey}
onClick={() => {
setReview({ ...review, Rating: index + 1 });
}}
onMouseOver={() => handleMouseOver(index + 1)}
/>
);
})}
</div>
<div id='message'></div>
<div>
<input
type='text'
placeholder='Your Name'
required
value={review.Name}
onChange={(e) => setReview({ ...review, Name: e.target.value })}
className='wpcf7-form-control'
/>
</div>
<div>
<input
type='text'
placeholder='Review Title'
required
value={review.Title}
onChange={(e) => setReview({ ...review, Title: e.target.value })}
className='wpcf7-form-control'
/>
</div>
<textarea
placeholder='Your comment'
required
value={review.Body}
onChange={(e) => setReview({ ...review, Body: e.target.value })}
className='wpcf7-form-control'
/>
<button type='submit' className='submit wpcf7-form-control wpcf7-submit' onClick={createReview}>
submit
</button>
</div>
</form>
</div>
<div className='themesflat-spacer clearfix' data-desktop={80} data-mobile={60} data-smobile={60} />
</div>
);
}
export default Ratings;
I want to submit and close with the button "save". change type to "button" type="submit" value="submit" onClick={ onClose } don't submit and don't close. I am using onClose for close the modal
import { useAppDispatch } from '../redux/hooks';
import { userInfo } from '../redux/model';
import { useForm } from 'react-hook-form';
import { ModalProps } from '../redux/model';
import { setList } from '../redux/slice';
type UI = userInfo;
const AddData: React.FC<ModalProps> = ({ isOpen, onClose }) => {
const [ page, setPage ] = useState(0);
const FormTitles = ["Invoice Address", "Bank Data", "Contact"];
const dispatch = useAppDispatch();
const { register, handleSubmit, formState: { errors, isValid }} = useForm<UI>({ mode: "all" });
const onSubmit = handleSubmit((data) => {
dispatch(setList(data));
});
return isOpen ? (<div className="viewModal">
<div className='modalContent'>
<form onSubmit={ onSubmit }>
<div className="contentForm">
<div className="closeX" onClick={ onClose }>x</div>
<div className="labels">
<div className="titleTxt">{ FormTitles[page] }</div>
{ page === 0 && (<>
<div className="labelInput">
<label htmlFor="additional">Additional</label>
<input { ...register("additional")} id="additional" />
</div>
<div className="labelInput">
... // content
</div>
<div className="labelInput">
... // content
</div>
</>)}
{ page === 1 && (<>
<div className="labelInput">
<label htmlFor="iban">IBAN</label>
<div className="dirCol">
<input { ...register("iban", { required: true, maxLength: 30 })} id="iban" />
<div className="required">{ errors.iban && "This is required!" }</div>
</div>
</div>
<div className="labelInput">
... // content
</div>
{ page === 2 && (<>
{/* *** fax *** */}
<div className="labelInput">
<label htmlFor="fax">Fax</label>
<input { ...register("fax")} id="fax" />
</div>
<div className="labelInput">
... // content
</div>
<div className="labelInput">
... // content
</div>
</div>
<div className="labelButton">
<button className="button2" onClick={ onClose }>Cancel</button>
{ page !== 0 && (<div className="button2 textCancel" onClick={() => { setPage((x) => x - 1)}}
>Previous</div>)}
{ page !== 2 && (<button className="button1" type="button" disabled={ !isValid } onClick={() => { setPage((x) => x + 1)}}
>Next</button>)}
{ page === 2 && (<>
<button className="button1" type="submit" value="submit" onClick={ onClose }>Save</button>
</>)}
</div>
</div>
</form>
</div>
</div>) : null
};
export default AddData;
here AddData off and on, onClose working with cancel and x button
import { useState } from 'react';
import AddData from './AddData';
import { useAppDispatch, useAppSelector } from '../redux/hooks';
import { removeList } from '../redux/slice';
const ListTable = () => {
const [ isModalOpen, setIsModalOpen ] = useState(false);
const toogleModal = () =>setIsModalOpen(!isModalOpen);
const dispatch = useAppDispatch();
const selector = useAppSelector((state) => state.users.list );
return <>
<AddData isOpen={ isModalOpen } onClose={ toogleModal }>
</AddData>
<nav>
<button onClick={ toogleModal }>Add</button>
</nav>
<div className='content'>
... // content
</div>
</>
};
export default ListTable;
Inside of the onClick for your save button you can call onSubmit and onClose.
import { useAppDispatch } from "../redux/hooks";
import { userInfo } from "../redux/model";
import { useForm } from "react-hook-form";
import { ModalProps } from "../redux/model";
import { setList } from "../redux/slice";
type UI = userInfo;
const AddData: React.FC<ModalProps> = ({ isOpen, onClose }) => {
const [page, setPage] = useState(0);
const FormTitles = ["Invoice Address", "Bank Data", "Contact"];
const dispatch = useAppDispatch();
const {
register,
handleSubmit,
formState: { errors, isValid },
} = useForm<UI>({ mode: "all" });
const onSubmit = handleSubmit((data) => {
dispatch(setList(data));
});
return isOpen ? (
<div className="viewModal">
<div className="modalContent">
<form onSubmit={onSubmit}>
<div className="contentForm">
<div className="closeX" onClick={onClose}>
x
</div>
<div className="labels">
<div className="titleTxt">{FormTitles[page]}</div>
{page === 0 && (
<>
<div className="labelInput">
<label htmlFor="additional">Additional</label>
<input {...register("additional")} id="additional" />
</div>
<div className="labelInput">{/* ... // content */}</div>
<div className="labelInput">{/* ... // content */}</div>
</>
)}
{page === 1 && (
<>
<div className="labelInput">
<label htmlFor="iban">IBAN</label>
<div className="dirCol">
<input
{...register("iban", { required: true, maxLength: 30 })}
id="iban"
/>
<div className="required">
{errors.iban && "This is required!"}
</div>
</div>
</div>
<div className="labelInput">... // content</div>
</>
)}
{page === 2 && (
<>
{/* *** fax *** */}
<div className="labelInput">
<label htmlFor="fax">Fax</label>
<input {...register("fax")} id="fax" />
</div>
<div className="labelInput">{/* ... // content */}</div>
<div className="labelInput">{/* ... // content */}</div>
</>
)}
</div>
<div className="labelButton">
<button className="button2" onClick={onClose}>
Cancel
</button>
{page !== 0 && (
<div
className="button2 textCancel"
onClick={() => {
setPage((x) => x - 1);
}}
>
Previous
</div>
)}
{page !== 2 && (
<button
className="button1"
type="button"
disabled={!isValid}
onClick={() => {
setPage((x) => x + 1);
}}
>
Next
</button>
)}
{page === 2 && (
<>
<button
className="button1"
type="submit"
value="submit"
onClick={() => {
onSubmit();
onClose;
}}
>
Save
</button>
</>
)}
</div>
</div>
</form>
</div>
</div>
) : null;
};
export default AddData;
I tried to get the button value when I click the button (onClick method).
I tried to do generally the way that is e.target.value but sometimes it returns an undefined or empty string. Even I tried to arrow function way that I find in here but still doesn't work. Could you help me with this problem? Which part is wrong or do I miss something?
This is the main part of my code:
updateProducts = e => {
// e.preventDefault();
let buttonValue = e.target.value;
console.log(buttonValue);
fetch('/data/MainProductsShoes.json', {})
.then(res => res.json())
.then(data => {
this.setState({
productsInfo: data,
// category_id: '',
});
});
};
and
<main className="contentsBody">
<div className="contentsLink">
<div className="viewAll">
<button onClick={this.updateProducts} value="viewAll">
<span>전체보기</span>
</button>
</div>
<div className="Shoes">
<button onClick={this.updateProducts} value="shoes">
<span>신발</span>
</button>
</div>
<div className="Clothes">
<button onClick={this.updateProducts} title="clothing">
<span>의류</span>
</button>
</div>
<div className="Supplies">
<button onClick={this.updateProducts} title="acc">
<span>용품</span>
</button>
</div>
</div>
Here's the complete code:
import React, { Component } from 'react';
import './Main.scss';
import COLOR_LISTS from './colorList';
import Products from './ProductsInfo/Products';
export class Main extends Component {
constructor() {
super();
this.state = {
productsInfo: [],
};
}
// const API = "DASDDADDAD" => 컴포넌트 마다 다 적용할수x
componentDidMount() {
fetch('/data/MainProducts.json', {})
.then(res => res.json())
.then(data => {
this.setState({
productsInfo: data,
});
});
}
updateProducts = e => {
// e.preventDefault();
let buttonValue = e.target.value;
console.log(buttonValue);
fetch('/data/MainProductsShoes.json', {})
.then(res => res.json())
.then(data => {
this.setState({
productsInfo: data,
// category_id: '',
});
});
};
// updateProducts = () => {
// console.log('clicked');
// fetch('/data/MainProducts.json', {
// method: 'GET',
// })
// .then(res => res.json())
// .then(data => {
// this.setState({
// productsInfo: data,
// category_id: this.state.category_id,
// });
// });
// };
// showToProductDetailPage = () => {
// const { productsInfo } = this.state;
// productsInfo &&
// productsInfo.map((product, idx) => (
// <Products key={idx} productInfo={product} />
// ));
// };
render() {
const { productsInfo } = this.state;
return (
<div className="MainWrapper">
<div className="sectionHeader">
<div className="sectionTitle">
<div className="sectionTitleCategory">
<span className="categoryName">Men</span>
<br />
<br />
<span>Men's 의류(12)</span>
</div>
<div className="sectionControl">
<button>필터</button>
<select name="list" className="productsFilter">
<option value="newestOrdeer">신상품순</option>
<option value="hightCostoOder">높은가격순</option>
<option value="lowCostOrder">낮은가격순</option>
</select>
</div>
</div>
</div>
<div className="contentsWrapper">
<aside className="contentsSide">
<div className="HorizontalLine" />
<div className="colors">
<span>색상</span>
<ul className="colorLists">
{COLOR_LISTS.map((color, idx) => {
return (
<li className="colorLayout" title="베이지" key={idx}>
<input type="checkbox" />
<label
className="checkboxLabel"
for="checkbox"
style={{ backgroundColor: color.colorProps }}
/>
<span className="productColor">{color.color_name}</span>
</li>
);
})}
</ul>
</div>
<div className="sizes">
<div className="HorizontalLine" />
<span>사이즈</span>
<div className="sizeLists">
<button title="230">230</button>
<button title="230">235</button>
<button title="230">240</button>
<button title="230">245</button>
<button title="230">250</button>
<button title="230">255</button>
<button title="230">260</button>
<button title="230">265</button>
<button title="230">270</button>
<button title="230">275</button>
<button title="230">280</button>
</div>
<div className="HorizontalLine" />
</div>
</aside>
<main className="contentsBody">
<div className="contentsLink">
<div className="viewAll">
<button onClick={this.updateProducts} value="viewAll">
<span>전체보기</span>
</button>
</div>
<div className="Shoes">
<button onClick={this.updateProducts} value="shoes">
<span>신발</span>
</button>
</div>
<div className="Clothes">
<button onClick={this.updateProducts} title="clothing">
<span>의류</span>
</button>
</div>
<div className="Supplies">
<button onClick={this.updateProducts} title="acc">
<span>용품</span>
</button>
</div>
</div>
<article className="productsMapping">
{productsInfo &&
productsInfo.map((product, idx) => (
<Products key={idx} productInfo={product} />
))}
</article>
</main>
</div>
</div>
);
}
}
export default Main;
change you updateProducts function to receive a string value representing the product name:
updateProducts = (name) => {
console.log(name);
fetch('/data/MainProductsShoes.json', {})
.then(res => res.json())
.then(data => {
this.setState({
productsInfo: data,
// category_id: '',
});
});
};
Then on each button pass the product name as an argument:
<button onClick={() => this.updateProducts('shoes')}>
Use event.currentTarget.value instead of event.target.value.
let buttonValue = e.currentTarget.value;
console.log(buttonValue);
event.target points to the element where the click event triggered. In your case that can be either span inside the button sometimes and that is when you get undefined value.
event.currentTarget points to the element where the event handler is attached which is the button.
I also notice some of the buttons have title property instead of value property.
<div className="viewAll">
<button onClick={this.updateProducts} value="viewAll">
<span>전체보기</span>
</button>
</div>
<div className="Shoes">
<button onClick={this.updateProducts} value="shoes">
<span>신발</span>
</button>
</div>
<div className="Clothes">
<button onClick={this.updateProducts} title="clothing">
<span>의류</span>
</button>
</div>
<div className="Supplies">
<button onClick={this.updateProducts} title="acc">
<span>용품</span>
</button>
</div>
Having an issue with a react form and I can't figure it out. I am getting TypeError: Cannot read property 'value' of undefined when submitting. The issue started when I added "location" to the form. Not sure how this is causing it to break as I am just adding another item to the form. I have attempted to fix any typos, and when I take out the "location" it submits with no issue.
import React from "react";
import Firebase from "firebase";
import config from "./config";
class App extends React.Component {
constructor(props) {
super(props);
Firebase.initializeApp(config);
this.state = {
pallets: []
};
}
componentDidMount() {
this.getUserData();
}
componentDidUpdate(prevProps, prevState) {
if (prevState !== this.state) {
this.writeUserData();
}
}
writeUserData = () => {
Firebase.database()
.ref("/")
.set(this.state);
console.log("DATA SAVED");
};
getUserData = () => {
let ref = Firebase.database().ref("/");
ref.on("value", snapshot => {
const state = snapshot.val();
this.setState(state);
});
};
handleSubmit = event => {
event.preventDefault();
let name = this.refs.name.value;
let QTY = this.refs.QTY.value;
let uid = this.refs.uid.value;
let location = this.refs.location.value;
if (uid && name && QTY && location) {
const { pallets } = this.state;
const devIndex = pallets.findIndex(data => {
return data.uid === uid;
});
pallets[devIndex].name = name;
pallets[devIndex].QTY = QTY;
pallets[devIndex].location = location;
this.setState({ pallets });
} else if (name && QTY && location) {
const uid = new Date().getTime().toString();
const { pallets } = this.state;
pallets.push({ uid, name, QTY, location });
this.setState({ pallets });
}
this.refs.name.value = "";
this.refs.QTY.value = "";
this.refs.uid.value = "";
this.refs.location.value = "";
};
removeData = pallet => {
const { pallets } = this.state;
const newState = pallets.filter(data => {
return data.uid !== pallet.uid;
});
this.setState({ pallets: newState });
};
updateData = pallet => {
this.refs.uid.value = pallet.uid;
this.refs.name.value = pallet.name;
this.refs.QTY.value = pallet.QTY;
this.refs.location.value =pallet.location;
};
render() {
const { pallets } = this.state;
return (
<React.Fragment>
<div className="container">
<div className="row">
<div className="col-xl-12">
<h1>Creating Pallet App</h1>
</div>
</div>
<div className="row">
<div className="col-xl-12">
{pallets.map(pallet => (
<div
key={pallet.uid}
className="card float-left"
style={{ width: "18rem", marginRight: "1rem" }}
>
<div className="card-body">
<h5 className="card-title">{pallet.name}</h5>
<p className="card-text">{pallet.QTY}</p>
<p className="card-text">{pallet.location}</p>
<button
onClick={() => this.removeData(pallet)}
className="btn btn-link"
>
Delete
</button>
<button
onClick={() => this.updateData(pallet)}
className="btn btn-link"
>
Edit
</button>
</div>
</div>
))}
</div>
</div>
<div className="row">
<div className="col-xl-12">
<h1>Add new pallet here</h1>
<form onSubmit={this.handleSubmit}>
<div className="form-row">
<input type="hidden" ref="uid" />
<div className="form-group col-md-6">
<label>Name</label>
<input
type="text"
ref="name"
className="form-control"
placeholder="Name"
/>
</div>
<div className="form-group col-md-6">
<label>QTY</label>
<input
type="text"
ref="QTY"
className="form-control"
placeholder="QTY"
/>
</div>
<div className="form-group col-md-6">
<label>Location</label>
<input
type="text"
ref="QTY"
className="form-control"
placeholder="Location"
/>
</div>
</div>
<button type="submit" className="btn btn-primary">
Save
</button>
</form>
</div>
</div>
</div>
</React.Fragment>
);
}
}
export default App;
You haven't created a ref named location
Change:
<input
type="text"
ref="QTY"
className="form-control"
placeholder="Location"
/>
to:
<input
type="text"
ref="location"
className="form-control"
placeholder="Location"
/>
Trying to get the "detail of the cards to open up a new index page, but I keep getting an error where it says "idC" is undefined or else it's "onClick" type error (which im assuming has to do with the idC). How do I make it so that the onClick works from the handleDetails and displays the displayPage?
class Products extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
value: "",
details_id: 1,
pageIndex: 1
};
//Handles filter change
this.handleChange = this.handleChange.bind(this);
this.handleSubmitS = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({ value: event.target.value });
}
handleSubmit(event) {
event.preventDefault();
console.log(this.state.value);
}
componentDidMount() {
axios
.get("/api/postings")
.then(res => {
console.log(res.data);
this.setState({
data: res.data
});
})
.catch(err => {
console.log(err);
});
}
displayPage = index => {
switch (index) {
case 0:
return (
<ProductDetails
idC={this.state.details_id}
handleIndex={this.handleIndex}
/>
);
case 1:
return (
<ProductsList
recipes={this.state.data}
handleDetails={this.handleDetails}
// handleChange={this.handleChange}
// handleSubmit={this.handleSubmit}
error={this.state.error}
/>
);
default:
}
};
handleIndex = index => {
this.setState({
pageIndex: index
});
};
handleDetails = (index, idC) => {
this.setState({
details_id: idC,
pageIndex: index
});
};
render() {
// const { image_url, title, recipe_id, publisher } = this.props.recipe;
// const { id, location, postStatus, postType, picture } = this.props.recipe;
// const {id} = this.props.recipe;
const { handleDetails } = this.props;
return (
//Search form
<div className="Search">
<form onSubmit={this.handleSubmit} class="form-inline my-2 my-lg-0">
<i class="fas fa-search" aria-hidden="true"></i>
<input
class="form-control-sm m1-3 w-75"
type="text"
placeholder="Search"
aria-label="Search"
value={this.state.value}
onChange={this.handleChange}
></input>
</form>
<Container>
<Row>
{this.state.data
.filter(searchingFor(this.state.value))
.map(data => (
<React.Fragment key={data.root}>
<div className="col-10 mx-auto col-md-6 col-lg-4 my-3">
<div className="card">
<img
src={data.picture}
className="img-card-top"
alt="recipe"
style={{ height: "14rem" }}
/>
<div className="card-body text-capitalized">
<h6>location: {data.location}</h6>
<h6 className="text-warning text-slanted">
postStatus: {data.postStatus}
</h6>
</div>
<div className="card-footer text-cen">
<button
type="button"
className="btn btn-primary text-capitalize"
onClick={() => handleDetails(0, idC)}
>
details
</button>
</div>
</div>
</div>
</React.Fragment>
))}
</Row>
</Container>
</div>
);
}
}
export default Products;
first one you can't set valid idC and index default 0 enter code here
class Products extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
value: "",
details_id: 1,
pageIndex: 1
};
//Handles filter change
this.handleChange = this.handleChange.bind(this);
this.handleSubmitS = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({ value: event.target.value });
}
handleSubmit(event) {
event.preventDefault();
console.log(this.state.value);
}
componentDidMount() {
axios
.get("/api/postings")
.then(res => {
console.log(res.data);
this.setState({
data: res.data
});
})
.catch(err => {
console.log(err);
});
}
displayPage = index => {
switch (index) {
case 0:
return (
<ProductDetails
idC={this.state.details_id}
handleIndex={this.handleIndex}
/>
);
case 1:
return (
<ProductsList
recipes={this.state.data}
handleDetails={this.handleDetails}
// handleChange={this.handleChange}
// handleSubmit={this.handleSubmit}
error={this.state.error}
/>
);
default:
}
};
handleIndex = index => {
this.setState({
pageIndex: index
});
};
handleDetails = (index, idC) => {
this.setState({
details_id: idC,
pageIndex: index
});
};
render() {
// const { image_url, title, recipe_id, publisher } = this.props.recipe;
// const { id, location, postStatus, postType, picture } = this.props.recipe;
// const {id} = this.props.recipe;
const { handleDetails } = this.props;
return (
//Search form
<div className="Search">
<form onSubmit={this.handleSubmit}
class="form-inline my-2 my-lg-0">
<i class="fas fa-search" aria-hidden="true"></i>
<input class="form-control-sm m1-3 w-75" type="text" placeholder="Search"
aria-label="Search"
value={this.state.value}
onChange={this.handleChange}>
</input>
</form>
<Container>
<Row>
{
this.state.data.filter(searchingFor(this.state.value)).map((data, index) =>
<React.Fragment key={data.root}>
<div className="col-10 mx-auto col-md-6 col-lg-4 my-3">
<div className="card">
<img
src={data.picture}
className="img-card-top"
alt="recipe"
style={{ height: "14rem" }}
/>
<div className="card-body text-capitalized">
<h6>location: {data.location}</h6>
<h6 className="text-warning text-slanted">
postStatus: {data.postStatus}
</h6>
</div>
<div className="card-footer text-cen">
<button
type="button"
className="btn btn-primary text-capitalize"
onClick={() => handleDetails(index, data.idC)} // set your details_id or _id
>
details
</button>
</div>
</div>
</div>
</React.Fragment>
)}
</Row>
</Container>
</div>
);
}
}
export default Products;