I'm having problems with the logic form.
So, I have a select form. Like this =>
So what I want is, when the user clicks on the "other" option, an input form will appear.
The question is, how to make the logic function?
My Code =
const ButtonModal = () => {
const [openModal, setOpenModal] = useState(false);
const [selectedOption, setSelectedOption] = useState(null);
const handleModal = () => setOpenModal(!openModal);
return (
<>
<button
onClick={handleModal}
className="bg-merah text-white font-bold text-sm rounded-2xl w-48 h-10 py-2 mb-6"
>
Perbarui Kompetitor
</button>
<Modal
center
open={openModal}
onClose={handleModal}
showCloseIcon={false}
>
<section className="grid justify-items-end">
<AiOutlineCloseCircle size={30} onClick={handleModal} />
</section>
<div className="flex items-center justify-center mb-4">
<section className="inline-flex gap-2">
<p className="font-bold text-center">Pembaruan Data Kompetitor</p>
</section>
</div>
<p>
Tambah data dengan memilih nama kompetitor yang tersedia atau masukkan
data baru.
</p>
<p className="font-bold mt-6">Nama Kompetitor</p>
<div class="flex justify-center">
<div class="mb-3 w-600 mr-6 mt-2">
<select
onChange={(e) => setSelectedOption(e.target.value)}
class="form-select appearance-none
block
w-full
px-3
py-1.5
mb-1
text-base
font-normal
text-gray-700
bg-white bg-clip-padding bg-no-repeat
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none"
aria-label="Default select example"
>
<option selected>Choose a competitor's name</option>
<option value="biznet">Biznet</option>
<option value="cbn">CBN</option>
<option value="first_media">First Media</option>
<option value="iconet">Iconet</option>
<option value="oxygen">Oxygen</option>
<option value="my_republik">My Republik</option>
<option value="other">Other</option>
</select>
</div>
</div>
{selectedOption === "other" && (
<div class="mb-6">
<input
class="w-[37.5rem] bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Masukan nama kompetitor..."
required
/>
</div>
)}
<div className="flex items-center justify-center">
<button
type="button"
class="inline-block px-6 py-2 border-2 border-red-600 text-red-600 font-medium text-xs leading-tight rounded hover:bg-black hover:bg-opacity-5 focus:outline-none focus:ring-0 transition duration-150 ease-in-out"
>
Kembali
</button>
<button
type="button"
class="inline-block ml-6 px-6 py-2.5 bg-gray-200 text-gray-700 font-medium text-xs leading-tight rounded shadow-md hover:bg-gray-300 hover:shadow-lg focus:bg-gray-300 focus:shadow-lg focus:outline-none focus:ring-0 active:bg-gray-400 active:shadow-lg transition duration-150 ease-in-out"
>
Ya, Keluar
</button>
</div>
</Modal>
</>
);
};
Related
I am developing a search bar that performs the search by calling an api, I encounter an error: Parsing error: Missing semicolon. The error comes from this part of the code:
const form = event.target as HTMLFormElement;
specifically between the event.target and the as. Could someone explain me the reason of this error and how to solve it?
import React, { FormEvent, useState, useEffect } from "react";
import Select, { SingleValue } from "react-select";
import { getCollegiate } from "../../api/drupalAPI";
import { Collegiate } from "#icofcv/common";
import Loader from "../spinner/Loader";
interface Props {
showModal: boolean;
closeModal: () => void;
}
export const ModalFilterCollegiate: React.FC<Props> = ({
children,
showModal,
closeModal,
}) => {
const [collegiateList, setCollegiateList] = useState<Collegiate[]>([]);
const [collegiateSearch, setCollegiateSearch] = useState("");
const searchForCollegiates = async (query: String): Promise<Collegiate[]> => {
const result = await fetch(`/collegiate?filter=${query}`);
return (await result.json()).results;
};
useEffect(() => {
(async () => {
const query = encodeURIComponent(collegiateSearch);
const response = await searchForCollegiates(query);
setCollegiateList(response);
})();
}, [collegiateSearch]);
const search = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
const form = event.target as HTMLFormElement;
const input = form.querySelector("#searchText") as HTMLInputElement;
setCollegiateSearch(input.value);
input.value = "";
};
return (
<>
<div>
{showModal ? (
<>
<div className="justify-center items-center flex overflow-x-hidden overflow-y-auto fixed inset-0 z-50 outline-none focus:outline-none">
<div className="relative p-2 w-full max-w-2xl h-full md:h-auto">
{/*content*/}
<div className="relative bg-white rounded-lg shadow">
{/*header*/}
<div className="flex justify-between items-start px-4 py-3 rounded-t border-b">
<h3 className="text-lg font-medium">Buscar Colegiado</h3>
<button
className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center"
onClick={closeModal}
>
<svg
aria-hidden="true"
className="w-5 h-5"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
</button>
</div>
{/*body*/}
<div className="relative px-3 py-3 flex-auto overflow-auto modal-body">
<form
className="searchForm"
onSubmit={(event) => search(event)}
>
<div className="grid md:grid-cols-2 md:gap-4">
<div className="relative z-0 w-full group my-2">
<label
htmlFor=""
className="block mb-2 text-xs font-medium text-stone-600"
>
Número colegiado
</label>
<input
name=""
type="text"
id=""
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
/>
<p className="mt-2 text-xs text-red-600 hidden">
Completa este espacio
</p>
</div>
</div>
<div className="grid md:grid-cols-2 md:gap-4">
<div className="relative z-0 w-full group my-2">
<label
htmlFor=""
className="block mb-2 text-xs font-medium text-stone-600"
>
Nombre
</label>
<input
name=""
type="text"
id="searchText"
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
/>
<p className="mt-2 text-xs text-red-600 hidden">
Completa este espacio
</p>
</div>
<div className="relative z-0 w-full group my-2">
<label
htmlFor=""
className="block mb-2 text-xs font-medium text-stone-600"
>
Apellidos
</label>
<input
name=""
type="text"
id=""
className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5"
/>
<p className="mt-2 text-xs text-red-600 hidden">
Completa este espacio
</p>
</div>
</div>
<div className="grid md:grid-cols-2 md:gap-4">
<div className="relative z-0 w-full group">
<label
htmlFor=""
className="block mb-2 text-xs font-medium text-stone-600"
>
Provincia
</label>
<select className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option>Cualquier Provincia</option>
</select>
<p className="mt-2 text-xs text-red-600 hidden">
Completa este espacio
</p>
</div>
<div className="relative z-0 w-full group">
<label
htmlFor=""
className="block mb-2 text-xs font-medium text-stone-600"
>
Tipo
</label>
<select className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
<option>Seleccionar tipo</option>
<option>Ejercientes</option>
<option>No ejercientes</option>
<option>Honorarios</option>
<option>Colegiados de honor</option>
</select>
<p className="mt-2 text-xs text-red-600 hidden">
Completa este espacio
</p>
</div>
</div>
<div className="flex items-center justify-end px-4 py-3 border-t border-solid border-slate-200 rounded-b gap-2">
<button
className="btn text-black text-sm background-transparent px-8 outline-none focus:outline-none focus:ring-teal-600 focus:border-teal-600"
type="button"
onClick={closeModal}
>
Cancelar
</button>
<button
className="btn bg-teal-600 hover:bg-teal-700 text-white text-sm active:bg-teal-700 px-8 outline-none focus:outline-none"
type="button"
>
Buscar
</button>
</div>
</form>
</div>
{/*footer*/}
{collegiateList.map((collegiate) => (
<tr key={collegiate.id} className="bg-white border-b">
<td className="py-2 px-6">{collegiate.color}</td>
<td className="py-2 px-6">{collegiate.collegiate}</td>
<td className="py-2 px-6">{collegiate.firstname}</td>
<td className="py-2 px-6">{collegiate.lastname}</td>
<td className="py-2 px-6">{collegiate.provincia}</td>
</tr>
))}
</div>
</div>
</div>
<div className="opacity-25 fixed inset-0 z-40 bg-black"></div>
</>
) : null}
</div>
</>
);
};
I am trying to make a clinic locator that when you put where you are, you get as a result the nearby clinics, I can not enter data in the imput, not even let me write and I can not find the problem.
import React, { useState, useEffect } from 'react'
import { getClinic } from '../../api/drupalAPI'
import {Clinic} from '#icofcv/common';
import Spinner from '../spinner/Spinner';
interface Props {
showModalLocator: boolean,
closeModalLocator: () => void
}
export const ClinicLocator: React.FC<Props> = ({ children, showModalLocator, closeModalLocator }) => {
const [clinicList, setClinicList] = useState<Clinic[]>([]);
const [clinicListFiltered, setClinicListFiltered] = useState<Clinic[]>([]);
const [searchClinic, setSearchClinic] = useState("");
const handleChange= (e) => async () => {
getClinic().then((response)=>{
console.log(response)
setClinicList(response);
setClinicListFiltered(response)
}).catch ( (error) => {
console.error(error);
throw error;
});
setSearchClinic(e.target.value);
filter(e.target.value);
}
const filter=(termSearch)=>{
const resultSearch= clinicList.filter((element)=>{
if(element.address?.toString().toLowerCase().includes(termSearch.toLowerCase())
|| element.province?.toString().toLowerCase().includes(termSearch.toLowerCase())
|| element.town?.toString().toLowerCase().includes(termSearch.toLowerCase())
){
return element;
}
});
setClinicListFiltered(resultSearch);
}
return (
<>
<div>
{showModalLocator ? (
<>
<div className="justify-center items-center flex overflow-x-hidden overflow-y-auto fixed inset-0 z-50 outline-none focus:outline-none">
<div className="relative p-2 w-full max-w-3xl h-full md:h-auto">
{/*content*/}
<div className="relative bg-white rounded-lg shadow">
{/*header*/}
<div className="flex justify-between items-start px-4 py-3 rounded-t border-b">
<h3 className="text-lg font-medium">Localizador de clinicas</h3>
<button className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center" onClick={closeModalLocator}>
<svg aria-hidden="true" className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
</svg>
</button>
</div>
{/*body*/}
<div className="relative px-3 py-3 flex-auto overflow-auto modal-body">
<h2 className="text-sm font-medium mb-2">¿Dónde te encuentras?</h2>
<input
value={searchClinic}
onChange={handleChange}
type="search"
className="w-100 bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2"
placeholder="Introduce una ubicación"
/>
<div className="py-3 border-b flex flex-col md:flex-row items-start md:items-center md:justify-between justify-start gap-2">
<div className="flex items-center">
<label className="inline-flex relative items-center mr-5 cursor-pointer">
<input type="checkbox" className="sr-only peer" checked/>
<div className="w-11 h-6 bg-gray-200 rounded-full peer peer-focus:ring-teeal-600
peer-checked:after:translate-x-full peer-checked:after:border-white after:content-['']
after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-teal-600"></div>
<span className="ml-2 text-xs font-medium text-gray-900">Centro privado</span>
</label>
</div>
<div className="flex items-center">
<label className="inline-flex relative items-center mr-5 cursor-pointer">
<input type="checkbox" className="sr-only peer" readOnly/>
<div className="w-11 h-6 bg-gray-200 rounded-full peer peer-focus:ring-teeal-600
peer-checked:after:translate-x-full peer-checked:after:border-white after:content-['']
after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-teal-600"></div>
<span className="ml-2 text-xs font-medium text-gray-900">con Mútuas</span>
</label>
</div>
<div className="flex items-center">
<label className="inline-flex relative items-center mr-5 cursor-pointer">
<input type="checkbox" className="sr-only peer" readOnly/>
<div className="w-11 h-6 bg-gray-200 rounded-full peer peer-focus:ring-teeal-600
peer-checked:after:translate-x-full peer-checked:after:border-white after:content-['']
after:absolute after:top-0.5 after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all peer-checked:bg-teal-600"></div>
<span className="ml-2 text-xs font-medium text-gray-900">con Compañías de Salud</span>
</label>
</div>
</div>
<div>
<h2 className="text-sm font-medium my-3">Resultados</h2>
<div className="w-100">
<iframe className="w-100" src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d2664.3238269926374!2d-0.3805919350162851!3d39.46959682083709!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0xd604f4bee0957f3%3A0x6686ff7d230b3965!2zQy4gZGUgU2FudC
BWaWNlbnQgTcOgcnRpciwgNjEsIHBpc28gMsK6LCBwdGEgMsKqLCA0NjAwMiBWYWzDqG5jaWEsIEVzcGHDsWE!5e0!3m2!1ses!2sus!4v1662388390673!5m2!1ses!2sus" loading="lazy"></iframe>
</div>
<div className="md:mt-4 overflow-auto relative py-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
<div className="card bg-white px-2 py-3 h-36 md:h-32">
{!clinicListFiltered ? <Spinner /> :
clinicListFiltered.map((clinic) => (
<button key={clinic.id} type="button" className="text-left">
<div className="flex items-center gap-2 md:gap-4 md:gap-4">
<img className="h-24 w-2/5 min-w-40 object-cover object-center rounded-lg" src="../carousel-1.svg" alt="#"/>
<div className="w-3/5">
<div className="text-md font-medium leading-5 clinic-title uppercase">{clinic.title}</div>
<div className="flex items-center gap-2">
<div className="text-neutral-500 text-sm">{clinic.propsPhone}</div>
<div className="text-neutral-500 text-sm">{clinic.mobile}</div>
</div>
<div className="text-teal-600 text-sm underline clinic-mail">{clinic.email}</div>
<div className="text-neutral-500 text-sm">{clinic.registry}</div>
</div>
</div>
</button>
))
}
</div>
{/* <div className="card bg-white px-2 py-3 h-36 md:h-32">
<button type="button" className="text-left">
<div className="flex items-center gap-2 md:gap-4 md:gap-4">
<img className="h-24 w-2/5 min-w-40 object-cover object-center rounded-lg" src="../carousel-1.svg" alt="#"/>
<div className="w-3/5">
<div className="text-md font-medium leading-5 clinic-title uppercase">AlamedaVLC</div>
<div className="flex items-center gap-2">
<div className="text-neutral-500 text-sm">963255652</div>
<div className="text-neutral-500 text-sm">963255652</div>
</div>
<div className="text-teal-600 text-sm underline clinic-mail">fisioalamedavlc#gmail.com</div>
<div className="text-neutral-500 text-sm">9947</div>
</div>
</div>
</button>
</div> */}
</div>
</div>
</div>
</div>
{/*footer*/}
<div className="flex items-center justify-end px-4 py-2 border-t border-solid border-slate-200 rounded-b gap-2">
<button className="btn text-black text-sm background-transparent px-8 outline-none focus:outline-none focus:ring-teal-600 focus:border-teal-600" type="button" onClick={closeModalLocator}>Cancelar</button>
<button className="btn bg-teal-600 hover:bg-teal-700 text-white text-sm active:bg-teal-700 px-8 outline-none focus:outline-none" type="button" onClick={closeModalLocator}>Buscar</button>
</div>
</div>
</div>
</div>
<div className="opacity-25 fixed inset-0 z-40 bg-black"></div>
</>
) : null}
</div>
</>
)
}
Try to change the line
const handleChange= (e) => async () => {
to
const handleChange = (e) => {
You're currently returning a function, which means that it doesn't get called. There is also no need for async as you don't have any await in the function.
handleChange returns a function which is never executed; remove the currying as it is not needed:
const handleChange= (e) => {
getClinic().then((response)=>{
console.log(response)
setClinicList(response);
setClinicListFiltered(response)
}).catch ( (error) => {
console.error(error);
throw error;
});
setSearchClinic(e.target.value);
filter(e.target.value);
}
The reason you cannot input anything is that React treats the input field as controlled component, which means that it itself won't take care of updating the fields value since you passed an initial value (of ""). With controlled components, you as the developer are required to handle the state outside of the input field, i.e. update the value attribute of the input component. Since that failed due to the mistake outlined above, the value of the input field remains fixed at "", thus not allowing you to type in the field.
Further reading:
Controlled components
Uncontrolled components
here I have a problem related to making the disable and enable button logic functions.
So, when the user selects the menu in the select option, the button that was originally disabled becomes enable and the color of the button changes too.
how to create such a function? Thanks.
before choosing, the button is disabled.
User selects menu.
The user after selecting the menu, the button changes to enable and the button color also changes.
My Code =
const ButtonModal = () => {
const [openModal, setOpenModal] = useState(false);
const [selectedOption, setSelectedOption] = useState(null);
const handleModal = () => setOpenModal(!openModal);
return (
<>
<button
onClick={handleModal}
className="bg-merah text-white font-bold text-sm rounded-2xl w-48 h-10 py-2 mb-6"
>
Perbarui Kompetitor
</button>
<Modal
center
open={openModal}
onClose={handleModal}
showCloseIcon={false}
>
<section className="grid justify-items-end">
<AiOutlineClose
size={20}
onClick={handleModal}
className="cursor-pointer"
/>
</section>
<div className="flex items-center justify-center mb-4">
<section className="inline-flex gap-2">
<p className="font-bold text-center">Pembaruan Data Kompetitor</p>
</section>
</div>
<p>
Tambah data dengan memilih nama kompetitor yang tersedia atau masukkan
data baru.
</p>
<p className="font-bold mt-6">Nama Kompetitor</p>
<div class="flex justify-center">
<div class="mb-3 w-600 mr-6 mt-2">
<select
onChange={(e) => setSelectedOption(e.target.value)}
class="form-select appearance-none
block
w-full
px-3
py-1.5
mb-1
text-base
font-normal
text-gray-700
bg-white bg-clip-padding bg-no-repeat
border border-solid border-gray-300
rounded
transition
ease-in-out
m-0
focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none"
aria-label="Default select example"
>
<option selected>Pilih nama kompetitor</option>
<option value="biznet">Biznet</option>
<option value="cbn">CBN</option>
<option value="first_media">First Media</option>
<option value="iconet">Iconet</option>
<option value="oxygen">Oxygen</option>
<option value="my_republik">My Republik</option>
<option value="other">Lainnya</option>
</select>
</div>
</div>
{selectedOption === "other" && (
<div class="mb-6">
<input
class="w-[37.5rem] bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
placeholder="Masukan nama kompetitor..."
required
/>
</div>
)}
<div className="flex items-center justify-center">
<button
onClick={handleModal}
type="button"
class="inline-block px-6 py-2 border-2 border-red-600 text-red-600 font-medium text-xs leading-tight rounded hover:bg-black hover:bg-opacity-5 focus:outline-none focus:ring-0 transition duration-150 ease-in-out"
>
Kembali
</button>
<button
type="button"
class="inline-block ml-6 px-6 py-2.5 bg-gray-200 text-gray-700 font-medium text-xs leading-tight rounded shadow-md hover:bg-gray-300 hover:shadow-lg focus:bg-gray-300 focus:shadow-lg focus:outline-none focus:ring-0 active:bg-gray-400 active:shadow-lg transition duration-150 ease-in-out"
disabled
>
Lanjutkan
</button>
</div>
</Modal>
</>
);
};
Bind the button's disabled attribute to the selectedOption state - is this what you're after?
And do the same for changing colour, using a ternary to set the value.
<button
onClick={handleModal}
disabled={!selectedOption}
style={{ background: selectedOption ? 'red': 'transparent' }}
className="bg-merah text-white font-bold text-sm rounded-2xl w-48 h-10 py-2 mb-6"
/>
EDIT: I think I saw you mention in a comment that it's the other button. Just set them on the other button then.
Also edited to bind to the more appropriate state selectedOption.
disabled={!selectedOption}
style={{ background: selectedOption ? 'red': 'transparent' }}
I have mapped a list of responses from my backend mongodb to my frontend. For each response, I have also added a button. I want to add an voteResponse function for my vote button. How can I continue to have access to my {response.respondee} and {response.response} in my voteResponse function?
{responses.map((response) => (
<div
key={response._id}
className='py-8 px-12 mb-12 bg-gray-50 border-b border-gray-100 transform transition duration-300 ease-in-out hover:-translate-y-2'
>
<NextLink href={`/responses/${response.response}`} passHref>
<div>
<div className='inline-block text-gray-900 mb-4'></div>
<h3 className='text-lg leading-normal mb-2 font-semibold text-black'>
{response.response}
</h3>
<p className='text-gray-500'>
{response.respondee.slice(0, 5)}...
{response.respondee.slice(38)}
</p>
</div>
</NextLink>
<div>
<button
type='submit'
className='inline-flex justify-center mt-3 py-1 px-3 border border-transparent shadow text-base font-medium rounded-md text-white bg-cyan-600 hover:bg-cyan-700 focus:outline-none'
onClick={voteResponse}
>
Vote
</button>
</div>
</div>
))}
You can do this by 2 ways. First is by making a separate component which is being rendered in map function and pass response in it through props then each component will have access to it's response.response and response.respondee.
funtion Response({response}){
const voteResponse = () =>{
console.log(response.response, response.respondee)
}
return(
<div key={response._id} className='py-8 px-12 mb-12 bg-gray-50 border-b border-gray-100 transform transition duration-300 ease-in-out hover:-translate-y-2'>
<NextLink href={`/responses/${response.response}`} passHref>
<div>
<div className='inline-block text-gray-900 mb-4'></div>
<h3 className='text-lg leading-normal mb-2 font-semibold text-black'>
{response.response}
</h3>
<p className='text-gray-500'>
{response.respondee.slice(0, 5)}... {response.respondee.slice(38)}
</p>
</div>
</NextLink>
<div>
<button type='submit' className='inline-flex justify-center mt-3 py-1 px-3 border border-transparent shadow text-base font-medium rounded-md text-white bg-cyan-600 hover:bg-cyan-700 focus:outline-none' onClick={voteResponse}>
Vote
</button>
</div>
</div>
)
}
//use it like this
{responses.map((response) => (
<Response response={response} key={response._id} />
))}
Second way to pass the index in voteResponse function and then through that index you can access the those variables like responses[index].response and responses[index].respondee.
{responses.map((response, index) => (
<div key={response._id} className='py-8 px-12 mb-12 bg-gray-50 border-b border-gray-100 transform transition duration-300 ease-in-out hover:-translate-y-2'>
<NextLink href={`/responses/${response.response}`} passHref>
<div>
<div className='inline-block text-gray-900 mb-4'></div>
<h3 className='text-lg leading-normal mb-2 font-semibold text-black'>
{response.response}
</h3>
<p className='text-gray-500'>
{response.respondee.slice(0, 5)}... {response.respondee.slice(38)}
</p>
</div>
</NextLink>
<div>
<button type='submit' className='inline-flex justify-center mt-3 py-1 px-3 border border-transparent shadow text-base font-medium rounded-md text-white bg-cyan-600 hover:bg-cyan-700 focus:outline-none' onClick={voteResponse}>
Vote
</button>
</div>
</div>
))}
Pass value to onClick prop: onClick={() => voteResponse(response)} and use it as parameter of voteResponse function:
const voteResponse = (res) => {
console.log("response.respondee is: ", res.respondee) //<=== response.respondee value is res.respondee value
console.log("response.response is: ", res.response)
}
{responses.map((response) => (
<div
key={response._id}
className='py-8 px-12 mb-12 bg-gray-50 border-b border-gray-100 transform transition duration-300 ease-in-out hover:-translate-y-2'
>
<NextLink href={`/responses/${response.response}`} passHref>
<div>
<div className='inline-block text-gray-900 mb-4'></div>
<h3 className='text-lg leading-normal mb-2 font-semibold text-black'>
{response.response}
</h3>
<p className='text-gray-500'>
{response.respondee.slice(0, 5)}...
{response.respondee.slice(38)}
</p>
</div>
</NextLink>
<div>
<button
type='submit'
className='inline-flex justify-center mt-3 py-1 px-3 border border-transparent shadow text-base font-medium rounded-md text-white bg-cyan-600 hover:bg-cyan-700 focus:outline-none'
onClick={() => voteResponse(response)
>
Vote
</button>
</div>
</div>
))}
I have a problem where I use getInitialProps to fetch data but I show on the web it doesn't appear but if my data is try console.log the data will appear accordingly
{this.props.siswa.map(siswa => {
{console.log(siswa)}
<div className="flex">
<div className="py-8 px-8 w-full lg:max-w-sm bg-white rounded-xl shadow-md hover:shadow-xl space-y-2 sm:py-4 sm:flex sm:items-center sm:space-y-0 sm:space-x-6 dark:bg-indigo-600 ml-0 lg:ml-3 sm:mt-2 md:w-full">
<img className="block mx-auto object-cover w-24 h-24 rounded-full sm:mx-0 sm:flex-shrink-0" src={`/img/siswa/${siswa.id}.jpg`} loading="lazy" />
<div className="text-center space-y-2 sm:text-left">
<div className="space-y-0.5">
<p className="text-lg text-black font-semibold dark:text-gray-200">
{siswa.panggilan}
</p>
<p className="text-gray-500 font-medium dark:text-gray-300">
{siswa.nama}
</p>
</div>
<button id="om" className="px-4 py-1 text-sm text-indigo-600 font-semibold rounded-full border border-indigo-400 hover:text-white hover:bg-indigo-600 hover:border-transparent focus:outline-none focus:ring-1 focus:ring-indigo-600 focus:ring-offset-2 dark:text-gray-200 dark:border-white dark:hover:text-gray-200 dark:hover:border-indigo-800 dark:hover:bg-indigo-800 dark:focus:ring-indigo-800 w-full md:w-2/4" onClick={() => this.setState({showModalSiswa: true})}>Detail</button>
</div>
</div>
</div>
})}
this is the data that comes up if I do console.log
{
id: '1',
nama: 'Ipsun',
panggilan: 'ipsun',
ttl: 'ipsun',
alamat: 'ipsun',
nope: '43143',
ig: '#ipsun',
line: null,
telegram: null,
tiktok: null,
fb: null,
linkedin: null,
pesan: 'ipsun'
}
{
id: '2',
nama: 'lorem',
panggilan: 'lorem',
ttl: 'lorem',
alamat: 'lorem',
nope: '41413',
ig: '#lorem',
line: null,
telegram: null,
tiktok: null,
fb: null,
linkedin: null,
pesan: 'lorem'
}
It's because you're not returning any jsx from your .map ;)
{this.props.siswa.map(siswa => {
{console.log(siswa)}
return (
<div className="flex">
<div className="py-8 px-8 w-full lg:max-w-sm bg-white rounded-xl shadow-md hover:shadow-xl space-y-2 sm:py-4 sm:flex sm:items-center sm:space-y-0 sm:space-x-6 dark:bg-indigo-600 ml-0 lg:ml-3 sm:mt-2 md:w-full">
<img className="block mx-auto object-cover w-24 h-24 rounded-full sm:mx-0 sm:flex-shrink-0" src={`/img/siswa/${siswa.id}.jpg`} loading="lazy" />
<div className="text-center space-y-2 sm:text-left">
<div className="space-y-0.5">
<p className="text-lg text-black font-semibold dark:text-gray-200">
{siswa.panggilan}
</p>
<p className="text-gray-500 font-medium dark:text-gray-300">
{siswa.nama}
</p>
</div>
<button id="om" className="px-4 py-1 text-sm text-indigo-600 font-semibold rounded-full border border-indigo-400 hover:text-white hover:bg-indigo-600 hover:border-transparent focus:outline-none focus:ring-1 focus:ring-indigo-600 focus:ring-offset-2 dark:text-gray-200 dark:border-white dark:hover:text-gray-200 dark:hover:border-indigo-800 dark:hover:bg-indigo-800 dark:focus:ring-indigo-800 w-full md:w-2/4" onClick={() => this.setState({showModalSiswa: true})}>Detail</button>
</div>
</div>
</div>
)
})}
Or you can return like this:
{this.props.siswa.map(siswa =>
<div className="flex">
<div className="py-8 px-8 w-full lg:max-w-sm bg-white rounded-xl shadow-md hover:shadow-xl space-y-2 sm:py-4 sm:flex sm:items-center sm:space-y-0 sm:space-x-6 dark:bg-indigo-600 ml-0 lg:ml-3 sm:mt-2 md:w-full">
<img className="block mx-auto object-cover w-24 h-24 rounded-full sm:mx-0 sm:flex-shrink-0" src={`/img/siswa/${siswa.id}.jpg`} loading="lazy" />
<div className="text-center space-y-2 sm:text-left">
<div className="space-y-0.5">
<p className="text-lg text-black font-semibold dark:text-gray-200">
{siswa.panggilan}
</p>
<p className="text-gray-500 font-medium dark:text-gray-300">
{siswa.nama}
</p>
</div>
<button id="om" className="px-4 py-1 text-sm text-indigo-600 font-semibold rounded-full border border-indigo-400 hover:text-white hover:bg-indigo-600 hover:border-transparent focus:outline-none focus:ring-1 focus:ring-indigo-600 focus:ring-offset-2 dark:text-gray-200 dark:border-white dark:hover:text-gray-200 dark:hover:border-indigo-800 dark:hover:bg-indigo-800 dark:focus:ring-indigo-800 w-full md:w-2/4" onClick={() => this.setState({showModalSiswa: true})}>Detail</button>
</div>
</div>
</div>
}
Alternatively, you can omit the return keyword by using an implicit return:
const ComponentTest = ({ siswa }) =>
siswa.map((siswa) => (
<div className="flex">
{console.log(siswa)}
<div className="py-8 px-8 w-full lg:max-w-sm bg-white rounded-xl shadow-md hover:shadow-xl space-y-2 sm:py-4 sm:flex sm:items-center sm:space-y-0 sm:space-x-6 dark:bg-indigo-600 ml-0 lg:ml-3 sm:mt-2 md:w-full">
<img
className="block mx-auto object-cover w-24 h-24 rounded-full sm:mx-0 sm:flex-shrink-0"
src={`/img/siswa/${siswa.id}.jpg`}
loading="lazy"
/>
<div className="text-center space-y-2 sm:text-left">
<div className="space-y-0.5">
<p className="text-lg text-black font-semibold dark:text-gray-200">
{siswa.panggilan}
</p>
<p className="text-gray-500 font-medium dark:text-gray-300">
{siswa.nama}
</p>
</div>
<button
id="om"
className="px-4 py-1 text-sm text-indigo-600 font-semibold rounded-full border border-indigo-400 hover:text-white hover:bg-indigo-600 hover:border-transparent focus:outline-none focus:ring-1 focus:ring-indigo-600 focus:ring-offset-2 dark:text-gray-200 dark:border-white dark:hover:text-gray-200 dark:hover:border-indigo-800 dark:hover:bg-indigo-800 dark:focus:ring-indigo-800 w-full md:w-2/4"
onClick={() => this.setState({ showModalSiswa: true })}
>
Detail
</button>
</div>
</div>
</div>
));
Note the console.log is within JSX, this is fine since it is wrapped with curly brackets and gets evaluated.