Cannot receive to get clicked button value in React.js - reactjs

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>

Related

Errors while trying to convert Class Component to Functional

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.

How do I send data to my backend by clicking on save the page with REACT

How is it possible to send these data (Taste, Trust, content of question all questions (which are in Tabs.jsx), everything except the description see the picture please) to my backend by clicking on 'Save the page'.In first part before putting any url inside, I really want to see the data in the console log for now I have nothing printed out except this message :
SyntheticBaseEvent {_reactName: "onClick", _targetInst: null, type: "click", nativeEvent: PointerEvent, target: HTMLButtonElement…}
I have 2 versions but I don't know the difference, what is better to use, I just saw these 2 ways in this forum.
export default function MenuItemDisplay() {
const [data, setData] = useState({
taste: "",
trust: ""
});
function onSubmit(e) {
e.preventDefault();
axios
.post("", {
trust: data.trust,
taste: data.taste
})
.then((res) => {
console.log(res.data);
});
}
function handleSubmit(e) {
const newData = { ...data };
newData[e.target.id] = e.target.value;
setData(newData);
console.log(e);
}
const onError = () => {
console.log("Error");
};
function Checkbox({ value }) {
const [checked, setChecked] = useState(true);
return (
<label>
<input
type="checkbox"
defaultChecked={checked}
onChange={() => setChecked(!checked)}
/>
{value}
</label>
);
}
return (
<>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown ... /> .
</div>
...
<Checkbox value={!!item.trust} />
</div>
...
<button
type="submit"
onClick= {handleSubmit}
> Save the content
</button>
</>
);
}
OR the same code with fetch :
export default function MenuItemDisplay() {
const [trust, setTrust] = useState("item.trust");
const [taste, setTaste] = useState("item.taste");
const [message, setMessage] = useState("");
let handle = async (e) => {
e.preventDefault();
try {
let res = await fetch("", {
method: "POST",
body: JSON.stringify({
trust: trust,
taste: taste
})
});
let resJson = await res.json();
if (res.status === 200) {
setTaste("");
setTrust("");
message("Success");
} else {
setMessage("Some error occured");
}
} catch (err) {
console.log(err);
}
};
return (
<>
<form onSubmit={hadle}>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown
style={styles.select}
options={TASTE}
defaultValue={TASTE.find((t) => t.label === item.taste)}
styleSelect={colourStyles}
isMulti={true}
/>
</div>
<div className="TextStyle">
{"Trust "}
<Checkbox value={!!item.trust} />
</div>
<div className="TextStyle"> Description : {item.description} </div>
<Tabs data={item.questions} />
</div>
<button>Save</button>
</form>
</>
);
}
Plus I have another form inside my MenuItemDisplay component that is Tabs.jsx. I really don't don't how can I deal with these 2 forms and how to 'trace' these data...
Here is my code
You can go with the following approaches.
Using a form element
You need to send the form data to the backend using AJAX calls. The most conventional way to do so is to use a JSX form element.
export default function MenuItemDisplay() {
...
return (
<form onSubmit={handleSubmit}>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown
style={styles.select}
options={TASTE}
defaultValue={TASTE.find((t) => t.label === item.taste)}
styleSelect={colourStyles}
isMulti={true}
/>
</div>
<div className="TextStyle">
{"Trust "}
<Checkbox value={!!item.trust} />
</div>
<div className="TextStyle"> Description : {item.description} </div>
<Tabs data={item.questions} />
</div>
<button type="submit"> Save the page</button>
</form>
);
}
Using a handleSubmit callback to the save button
Another way to do it using the button to send the request to the backend when clicked.
export default function MenuItemDisplay() {
...
return (
<>
<h1> {item.name} </h1>
<div>
<div className="TextStyle">
{"Taste "}
<Dropdown
style={styles.select}
options={TASTE}
defaultValue={TASTE.find((t) => t.label === item.taste)}
styleSelect={colourStyles}
isMulti={true}
/>
</div>
<div className="TextStyle">
{"Trust "}
<Checkbox value={!!item.trust} />
</div>
<div className="TextStyle"> Description : {item.description} </div>
<Tabs data={item.questions} />
</div>
<button onClick={handleSubmit}> Save the page</button>
</>
);
}
All you need to do is define the handleSubmit callback. If you use the form element, you'd need to prevent the default form submission behavior.
async function handleSubmit(e) {
e.preventDefault(); // if you use the form tag
// validate the data here
// use fetch or axios or any other 3rd party library to send data to the back end
// receive response from backend
// do something with the response
}

REACT JS FIREBASE FIRESTORE- how can i update my field in a document?

here is my manageexam.jsx file
this is where the update happen when i click the manage button on the table. i want to update a specific document id (3BelYq7lMxRNrWKknCRK- this is a sample of my document id but ofcourse there will be a lot of document id when i will add more inside the collection.) but i want to update the fields without manually adding the document Id that i want to update.
const ManageExam = () => {
const [description,setDesc]=useState("")
const [title,setTitle]=useState("")
function handleUpdate(e){
e.preventDefault();
const examcollref = doc(db,'Exams' "3BelYq7lMxRNrWKknCRK")
updateDoc(examcollref,{
title:title,
description:description
} ).then(response => {
alert("updated")
}).catch(error =>{
console.log(error.message)
})
}
return (
<div className="manageExam">
<Sidebar/>
<div className="manageExamContainer">
<div className="examInfo">
<h1>Manage Exam</h1>
</div>
<div className="left">
<div className="leftForm">
<div className="leftTitle">
Exam information
</div>
<br />
<div className="leftTitle">
</div>
<form onSubmit={handleUpdate}>
<label >Exam Title</label>
<input
type="text"
placeholder={title.doc}
value={title}
onChange={e => setTitle(e.target.value)}/>
<label htmlFor="">Description</label>
<textarea
id="desc"
cols="30"
rows="7"
value={description}
onChange={e =>setDesc(e.target.value)}
></textarea>
<button type="submit">Update</button>
</form>
</div>
</div>
<div className="right">
<div className="rightForm">
<div className="rightTitle">
Add Questions
<Link to= {`add_question`}style={{textDecoration:"none"}} className="link" >
Add new
</Link>
</div>
<div className="rightContainer">
{/* <p>1. What is the Meaning of db?</p> */}
{/* <div>
<input type="radio" name="option1" value="database" checked/>
<label htmlFor="">database</label>
</div>
<div>
<input type="radio" name="option2" value="data" disabled/>
<label htmlFor="">data</label>
</div>
<div>
<input type="radio" name="option3" value="databytes" disabled/>
<label htmlFor="">databytes</label>
</div>
<div>
<input type="radio" name="option4" value="databoard" disabled/>
<label htmlFor="">databoard</label>
</div>
<br />
<button>update</button>
<button>delete</button> */}
</div>
</div>
</div>
</div>
</div>
)
}
export default ManageExam
export const Examtable = ({id}) => {
const [list,setExamlist] = useState([])
// function to call the list from the firestore
useEffect (()=>{
const unsub = onSnapshot(
collection(db, "Exams"), //"exams -> pangalan ng database/("collection") ko"
(snapShot) => {
let list = [];
snapShot.docs.forEach((doc) => {
list.push({ id: doc.id, ...doc.data() });
});
setExamlist(list);
console.log(list.id);
},
(error) => {
console.log(error);
}
);
return () => {
unsub();
};
},[]);
const handleDelete = async (id) => {
alert("Do you want to delete?")
//window.confirm("Are you sure you want to delete?");
try {
await deleteDoc(doc(db, "Exams", id));
setExamlist(list.filter((item) => item.id !== id));
console.log(id)
} catch (err) {
console.log(err);
}
};
const actionColumn = [{field: "action", headerName: "Action", width: 200, renderCell:(params)=>{
return(
<div className="cellAction">
<div className="manageButton"> {/*/exam/manage_exam*/}
<Link to={`/exam/manage_exam/${params.row.id}`} style={{textDecoration:"none"}} className="link" >
Manage
</Link>
</div>
<div className="deleteButton" onClick={() => handleDelete(params.row.id)}>Delete</div>
</div>
)
}}];
return (
<div className="examtable" >
<div className="examtableTitle">
Exam
<Link to="/exam/new_exam/" style={{textDecoration:"none"}} className="link">
Add new
</Link>
</div>
<DataGrid
className="datagrid"
rows={list} //eto mga list nung nasa firebase
columns={examColumns.concat(actionColumn)}
pageSize={9}
rowsPerPageOptions={[9]}
checkboxSelection
/>
</div>
)
}
export default Examtable
here is the examtable.jsx where all the document in the collection will be displayed.
when i click the manage button, the url will display like this (localhost:3000/exam/manageexam/3BelYq7lMxRNrWKknCRK,, its because i click on this document but i cant update it at all because the console always said the id was undefined. i hope you understand what im saying
Because your pass id with Link in Examtable file.I think u must use useParams from react-router-dom in ur ManageExam.
First you need add id in your route path file, like this.
path: '/exam/manageexam/:id'
And then, in ur ManageExam.
import {useParams} from 'react-router-dom'
const ManageExam = () => {
const {id} = useParams()
const [description,setDesc]=useState("")
const [title,setTitle]=useState("")
function handleUpdate(e){
e.preventDefault();
const examcollref = doc(db,'Exams', id)
updateDoc(examcollref,{
title:title,
description:description
} ).then(response => {
alert("updated")
}).catch(error =>{
console.log(error.message)
})

React modal hidden.bs.modal event dosen't work?

Modal.js
import React from 'react';
import $ from 'jquery';
const Modal = (props) => {
function onClickHandler(e) {
fetch(
'http://reactapi.test/api/product/delete/' +
e.target.attributes.guid.value,
{
method: 'get',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
}
)
.then((response) => response.json())
.then((data) => {
console.log(data);
});
}
function onModalDismissEvent(e) {
props.onClose(false);
}
$('#exampleModal').on('hidden.bs.modal', (e) => {
console.log(e);
});
return (
<div
className='modal fade'
id='exampleModal'
tabIndex='-1'
aria-labelledby='exampleModalLabel'
aria-hidden='true'
>
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-header'>
<h5 className='modal-title' id='exampleModalLabel'>
Resimler
</h5>
<button
type='button'
className='close'
data-dismiss='modal'
aria-label='Close'
onClick={onModalDismissEvent}
>
<span aria-hidden='true'>×</span>
</button>
</div>
<div className='modal-body'>
{props.product.slider.map((e) => {
return (
<div key={e.products_slider_guid}>
<img
height='150px'
src={'http://example.test/' + e.image}
alt={e.created_at}
/>
<button className='btn btn-outline-primary mr-2'>
Update
</button>
<button
onClick={onClickHandler}
className='btn btn-outline-danger mr-2'
guid={e.products_slider_guid}
>
Delete
</button>
</div>
);
})}
</div>
<div className='modal-footer'>
<button className='btn btn-outline-primary mr-4' type='button'>
Save
</button>
</div>
</div>
</div>
</div>
);
};
export default Modal;
Main.js
import React, { useContext, useState } from 'react';
import ProductContext from '../store/product-context';
import Modal from './Modal';
const Main = (props) => {
const [productImageHandler, setProductImageHandler] = useState(false);
const [findProductHandler, setFindProductHandler] = useState('');
const productCtx = useContext(ProductContext);
const onClickHandler = (event) => {
const findProduct = productCtx.items.find((item) => {
return item.product_guid === event.target.attributes.guid.value;
});
setFindProductHandler(findProduct);
setProductImageHandler(true);
};
const onCloseHandler = (e) => {
setProductImageHandler(e);
};
return (
<div>
<main ref={(modal) => modal} role='main' className='container mt-5'>
<div className='row'>
<div className='col-xl-12'>
{productCtx.items.map((item) => {
return (
<div key={item.id} className='list-group'>
<div className='list-group-item d-flex justify-content-between align-items-center'>
{item.name}
<div>
<button
className='btn btn-outline-info mr-2'
data-toggle='modal'
data-target='#exampleModal'
onClick={onClickHandler}
guid={item.product_guid}
>
Images
</button>
<button className='btn btn-outline-danger mr-2'>
Delete
</button>
</div>
</div>
</div>
);
})}
</div>
</div>
{productImageHandler && (
<Modal onClose={onCloseHandler} product={findProductHandler} />
)}
</main>
</div>
);
};
export default Main;
Modal hidden listener never trigger.
I'm trying to trigger the closing event when clicking the modal backdrop, but it doesn't work.
Is there anyone who can help, I'm not sure if I did the logic right now, I just started writing react
I've been dealing with it since yesterday morning React is a bit complicated core javascript is easier :)
after getting a better understanding of your issue at hand, you can add another prop to help to determine whether to show the component or keep it hidden. on each change on the variable in the useEffect array the function will trigger, check out react's docs on useEffect
Here's a simple example:
import React, { useEffect } from 'react';
const Modal = (props) => {
function onModalDismissEvent(e) {
props.onClose(false);
}
useEffect(() => {
return () => {
console.log("changed");
};
}, [props.hidden]) // "hidden" could be replaced with "closed" if such a prop exists that matches "props.onClose"
return (
<div
className='modal fade'
id='exampleModal'
tabIndex='-1'
aria-labelledby='exampleModalLabel'
aria-hidden='true'
>
<div className='modal-dialog'>
<div className='modal-content'>
<div className='modal-header'>
<h5 className='modal-title' id='exampleModalLabel'>
Resimler
</h5>
<button
type='button'
className='close'
data-dismiss='modal'
aria-label='Close'
onClick={onModalDismissEvent}
>
<span aria-hidden='true'>×</span>
</button>
</div>
<div className='modal-body'>
<Product product={props.product} />
</div>
<div className='modal-footer'>
<button className='btn btn-outline-primary mr-4' type='button'>
Save
</button>
</div>
</div>
</div>
</div>
);
};
export default Modal;
//Product.jsx
const Product = ({ product }) => {
function onClickHandler(e) {
fetch(
'http://reactapi.test/api/product/delete/' +
e.target.attributes.guid.value,
{
method: 'get',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
}
)
.then((response) => response.json())
.then((data) => {
console.log(data);
});
}
return (
{
product.slider.map((e) => {
return (
<div key={e.products_slider_guid}>
<img
height='150px'
src={'http://example.test/' + e.image}
alt={e.created_at}
/>
<button className='btn btn-outline-primary mr-2'>
Update
</button>
<button
onClick={onClickHandler}
className='btn btn-outline-danger mr-2'
guid={e.products_slider_guid}
>
Delete
</button>
</div>
);
})
}
)
}
Thank you for your help, I understand what you mean.

Can't figure out why the onClick handle isn't working. It says "idC" is undefined

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;

Resources