I have a problem with useFetch. I already apologize for my bad English.
Basically I have a button that clicking it must change the value of "cardname" which consequently calls useFetch and changes "cardport". But this is not the case. Can someone help me? Thanks.
This Fetch request
import { useEffect, useState } from 'react';
const useFetch = ({ url , cardname}) => {
const [card, setCard] = useState(null);
useEffect(() => {
fetch(url + cardname)
.then((result) => {
return result.json();
})
.then((data) => {
setCard(data);
});
}, []);
return { card }
}
export default useFetch
And this is the component with the button.
import React from 'react';
import { Link } from 'react-router-dom';
import { useState } from 'react';
import useFetch from '../hooks/useFetchCard';
const SearchBar = () => {
const url = "https://api.scryfall.com/cards/named?fuzzy=";
const [cardname, setCardname] = useState("fireball");
let cardport = useFetch({url , cardname});
function getInputValue() {
let inputVal = document.getElementById("searchtext").value
setCardname(inputVal);
console.log(cardname);
console.log(inputVal)
console.log(cardport)
}
return (
<div className="flex justify-center py-12">
<div className="mb-3 xl:w-96">
<div className="input-group relative flex flex-nowrap items-stretch w-full h-12 mb-4">
<input type="search" className="form-control relative flex-auto min-w-0 block w-full px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding border border-solid border-gray-300 rounded-l-lg transition ease-in-out m-0 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none" placeholder="Search" aria-label="Search" aria-describedby="button-addon2" id="searchtext"/>
<button className="btn inline-block px-6 py-2.5 bg-blue-600 text-white font-medium text-xs leading-tight uppercase rounded-r-lg shadow-md hover:bg-blue-700 hover:shadow-lg focus:bg-blue-700 focus:shadow-lg focus:outline-none focus:ring-0 active:bg-blue-800 active:shadow-lg transition duration-150 ease-in-out flex items-center transition-all ease-in-out hover:-translate-y hover:scale-125 hover:rounded duration-300" type="button" id="button-addon2" onClick={getInputValue}>
<Link to="/searchpage"><svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" className="w-4" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path fill="currentColor" d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"></path>
</svg></Link>
</button>
</div>
</div>
</div>
)
}
export default SearchBar
Related
I have watched countless videos and tried to implement suggestions from here and edited the code more than I can remember. Could someone please let me know what I am doing wrong here? I am trying to get the search to go through the data and filter the cards.
The data loads fine but there are some errors in console
When I try searching, once I type anything letter. The page goes blank
And console looks like this, Cannot read properties of undefined (reading 'filter') is suggested to be an error if item received is not an array, but the results shows array.
.
Here is my code. I am trying to learn so I understand this is very messy and should be in components.
import React from 'react';
import { useState } from 'react';
import axios from 'axios';
import { useEffect } from 'react';
function App() {
const [data, setData] = React.useState([]);
// const [searchTerm, setSearchTerm] = React.useState('');
const [searchTerm, setSearchTerm] = useState('');
const handleChange = event => {
setSearchTerm(event.target.publications);
};
useEffect(() => {
axios.get('https://api.**url.com/api/v1/content/publications?limit=50',{
headers: {
'X-AUTH-TOKEN' : '22bc08a8***2995da615c'
}
})
.then(response => {
console.log(response.data);
setData(response.data.data);
});
}, []);
return(
<div>
<h1>Publication title goes here </h1>
{/* Search */}
<div className='App'>
<input type="text" placeholder='Search' onChange={handleChange}/>
</div>
{/* Search end*/}
<div className="px-10 py-10 grid gap-4 md:grid-cols-4">
{
data.filter((publications) =>{
if (searchTerm == "") {
return publications}
// else if (data.publications.filter(item => item.toLowerCase().includes(searchTerm.toLowerCase())))
{data.publications.filter(item => item.toLowerCase().includes(searchTerm.toLowerCase()))
{
return publications
}
}}).map(publications =>
{ return (
// card
<div className="user" key={publications.id} className="container mx-auto max-w-4xl">
<div class="max-w-sm bg-white border border-gray-200 hover:bg-gray-100 rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700">
<a href="#">
<img class="rounded-t-lg" src="/docs/images/blog/image-1.jpg" alt="" />
</a>
<div class="p-5">
<a href="#">
<h2 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" strokeWidth={1.5} stroke="currentColor" className="w-6 h-6">
<path strokeLinecap="round" strokeLinejoin="round" d="M16.5 3.75V16.5L12 14.25 7.5 16.5V3.75m9 0H18A2.25 2.25 0 0120.25 6v12A2.25 2.25 0 0118 20.25H6A2.25 2.25 0 013.75 18V6A2.25 2.25 0 016 3.75h1.5m9 0h-9" />
</svg>
{publications.description}</h2>
</a>
<p class="mb-3 font-normal text-gray-700 dark:text-gray-400">Author: {publications.author}.</p>
<a href="#" class="inline-flex items-center px-3 py-2 text-sm font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
Last Publication
<svg aria-hidden="true" class="w-4 h-4 ml-2 -mr-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</a>
</div>
</div>
</div>
)
}
)
}
</div>
</div>
)
}
export default App;
The errors are showing up in your console, because you have to use className instead of class in React. You are using class in your card component. The other HTML attributes have to be written in camel case, so fill-rule becomes fillRule and clip-rule becomes clipRule.
For the issues with your filter, you should have a look at the docs for the Array.filter() and String.includes() methods. You can't filter an object with the includes method.
Also Cannot read properties of undefined (reading 'filter') is showing up, because data.publications IS undefined. Start using Typescript and these errors won't happen again.
Here is an example of how your filter could look like:
data.filter((publication) => {
// If no search term is set, return true
if (!searchTerm) {
return true
}
// If either the publication description or the author contain the search term, return true
if (publication.description.toLowerCase().includes(searchTerm.toLowerCase()) || publication.author.toLowerCase().includes(searchTerm.toLowerCase())) {
return true
}
// If there is a search term and neither the description nor the author contain the search term, return false
return false
})
as the title states I am creating a website using NextJS styled with TailwindCSS. However, there is a small and annoying issue with my code.
Here is my code below for the MainContent of the page:
"use client"
import React, {useState} from 'react';
export default function MainContent(){
const [eventTerm, setSearchTerm] = useState('');
const [zipCode, setZipCode] = useState('');
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setSearchTerm(event.currentTarget.value);
}
const handleZipChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setZipCode(event.currentTarget.value);
}
const handleSubmit = (event: React.ChangeEvent <HTMLButtonElement>) => {
event.preventDefault();
// Perform search functionality here
console.log(eventTerm);
console.log(zipCode);
}
return (
<main>
<div className = "max-w-7xl mx-5 px-5 sm:px-6 lg:px-8 my-auto py-9 mt-20 text-center">
<h1 className = "font-rowdies md:text-7xl text-white sm:text-center md:text-left my-3">Test, <br/> Test </h1>
<div className = "my-auto py-5">
<small className = "font-rowdies md:text-3xl text-white md:block md:text-left my-1 flex-wrap sm:text-2xl break-words">Test</small>
<div className="my-auto py-5 md:text-left">
<form className = "relative rounded-lg bg-transparent">
<input type="text" placeholder="Find a Service" defaultValue={eventTerm} onChange={handleChange} className="form-input mr-2 py-2 px-10 rounded-md leading-5 focus:outline-none focus:shadow-outline-indigo-500 w-800 text-center font-rowdies"/>
<input type="text" placeholder="Zip Code" defaultValue={zipCode} onChange={handleZipChange} className="form-input py-2 rounded-md leading-5 focus:outline-none focus:shadow-outline-indigo-500 w-21 text-center hidden md:inline font-rowdies"/>
<button className = "bg-gray-900 text-white ml-2 px-3 py-2 rounded-md text-l font-rowdies hover:text-secondary hover:bg-white">Lets Go!</button>
</form>
</div>
</div>
</div>
</main>
)
}
The errors I am getting in chrome are:
Error: Hydration failed because the initial UI does not match what was rendered on the server.
Warning: Did not expect server HTML to contain a in .
The issue seems to stem from this line only after refreshing the page not on the initial load
<input type="text" placeholder="Zip Code" defaultValue={zipCode} onChange={handleZipChange} className="form-input py-2 rounded-md leading-5 focus:outline-none focus:shadow-outline-indigo-500 w-21 text-center hidden md:inline font-rowdies"/>
I say this because whenever I delete this line the 2 errors go away and my website works just fine.
In addition to this, I sent my friend the file and it ran fine on his computer. Stuff that I tried included checking that my dependencies were up-to-date and clearing my cache and cookies as well as other things with my code.
Any help would be greatly appreciated. I will also add a few more code snippets as well as a directory structure image.
Thanks!
HomePage.tsx
import React, { MouseEventHandler, useState } from 'react';
import { Disclosure, Menu, Transition } from '#headlessui/react'
import '../styles/globals.css'
import MainContent from './MainContent';
export default function (){
const [isOpen, setIsOpen] = useState(false);
return (
<>
<header>
<div className = "items-center">
<nav className = "justify-between bg-secondary">
<div className = "mx-5 px-5 sm:px-6">
<div className = "relative flex items-center justify-between h-16">
<div className = "flex flex-grow-1 flex-shrink-1">
Portfolio
</div>
<div className = "hidden md:block items-end justify-end">
<div className = "ml-10 flex items-end space-x-4">
<button className = "bg-primary text-white px-3 py-2 rounded-md text-l font-rowdies hover:text-primary hover:bg-secondary">Join as a Pro</button>
Log In
Sign Up
About Us
</div>
</div>
<div className="-mr-2 flex md:hidden place-content-center">
<button
onClick={() => setIsOpen(!isOpen)}
type="button"
className="bg-gray-900 inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-800 focus:ring-white"
aria-controls="mobile-menu"
aria-expanded="false"
>
<span className="sr-only">Open main menu</span>
{!isOpen ? (
<svg
className="block h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4 6h16M4 12h16M4 18h16"
/>
</svg>
) : (
<svg
className="block h-6 w-6"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
aria-hidden="true"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
)}
</button>
</div>
</div>
</div>
<Transition
show={isOpen}
enter="transition ease-out duration-1000 transform"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="transition ease-in duration-75 transform"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
{(ref) => (
<div className="md:hidden text-center bg-secondary" id="mobile-menu">
<div ref={ref} className="px-2 pt-2 pb-3 space-y-1 sm:px-3">
Log In
Sign Up
About Us
<button className = "bg-primary text-white px-3 py-2 rounded-md text-l font-rowdies block mx-auto hover:text-primary hover:bg-secondary">Join as a Pro</button>
</div>
</div>
)}
</Transition>
</nav>
</div>
</header>
<MainContent />
</>
)
}
Page.tsx
"use client";
import Image from 'next/image'
import { Inter } from '#next/font/google'
import styles from './page.module.css'
const inter = Inter({ subsets: ['latin'] })
import { useRouter } from "next/navigation";
import Homepage from '#/components/Homepage';
import MainContent from '#/components/MainContent';
import { Main } from 'next/document';
export default function Home() {
return (
<>
<Homepage />
</>
)
}
Image of all my dependencies and their versions
When I disabled the LastPass browser extension the problem went away. LastPass injects HTML post-load that throws off the comparison between SSR and client.
could someone help on how to get all data from this console log? I am trying to display all the details in individual tailwind cards but not sure how to get the data. Thank you for your time.
axios.get('https://api.url**.com/api/v1/content/publications',{
headers: {
'X-AUTH-TOKEN' : '22***8a8369317***********'
}
}
)
.then(response => {
console.log (response.data)
It works and I get the results below in console.
when I tried console.log (response.data.0.pdf) for example, it gives an error "Parsing error: Unexpected token, expected".
Is it possible to get all the data under publications into individual cards?
<div class="max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700">
<a href="#">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">**{author}**</h5>
</a>
<p class="mb-3 font-normal text-gray-700 dark:text-gray-400">
**{pdf}**
**{id}**
**{etc}**</p>
<a href="#" class="inline-flex items-center px-3 py-2 text-sm font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">
Read more
<svg aria-hidden="true" class="w-4 h-4 ml-2 -mr-1" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</a>
</div>
Thanks again for your time.
From what I can tell it seems you are already fetching all the data since the response is an array. It seems like your question is then how to save and render the response data.
Create a local state variable to hold the fetched data. When this state is updated React will trigger a rerender with the latest state enclosed in scope.
const [data, setData] = React.useState([]);
Fetch the data in a component lifecycle method/hook, e.g. useEffect when the component mounts, and enqueue a state update to save the fetched data.
useEffect(() => {
axios.get('https://api.url**.com/api/v1/content/publications',{
headers: {
'X-AUTH-TOKEN' : '22***8a8369317***********'
}
})
.then(response => {
console.log(response.data);
setData(response.data); // <-- save response to state
});
}, []);
Render the local state to JSX. Arrays are typically mapped to JSX, e.g. Array.prototype.map. Each mapped element object is accessible in the map callback, e.g. item.author. Don't forget to also include a key prop on the outer-most mapped element. The React key is used as part of React's reconciliation process when it's computing what needs to refreshed to the DOM.
{data.map(item => (
<div
key={item.id}
class="max-w-sm p-6 bg-white border border-gray-200 rounded-lg shadow-md dark:bg-gray-800 dark:border-gray-700"
>
<a href="#">
<h5 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">
{item.author}
</h5>
</a>
<p class="mb-3 font-normal text-gray-700 dark:text-gray-400">
{item.pdf}
{item.id}
{item.etc}
</p>
<a
href="#"
class="inline-flex items-center px-3 py-2 text-sm font-medium text-center text-white bg-blue-700 rounded-lg hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800"
>
Read more
<svg
aria-hidden="true"
class="w-4 h-4 ml-2 -mr-1"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z"
clip-rule="evenodd"
/>
</svg>
</a>
</div>
))}
I recently came across this carousel Tailwind component (https://codesandbox.io/s/react-multi-item-carousel-uvmchp?file=/src/carousel.jsx).
I wanted the carousel items to enlargen on hover, so I made a change (namely adding hover:scale-125 transform-gpu transition duration-150 ease-in-out and removing overflow-hidden), but in doing so the left and right arrows of the carousel no longer work.
How can I fix this?
My code is here: https://codesandbox.io/s/react-multi-item-carousel-forked-jebmii?file=/src/carousel.jsx:0-4494
import { useState, useRef, useEffect } from "react";
import data from "./data.json";
const CollectionCarousel = () => {
const maxScrollWidth = useRef(0);
const [currentIndex, setCurrentIndex] = useState(0);
const carousel = useRef(null);
const movePrev = () => {
if (currentIndex > 0) {
setCurrentIndex((prevState) => prevState - 1);
}
};
const moveNext = () => {
if (carousel.current.offsetWidth * currentIndex <= maxScrollWidth.current) {
setCurrentIndex((prevState) => prevState + 1);
}
};
const isDisabled = (direction) => {
if (direction === "prev") {
return currentIndex <= 0;
}
if (direction === "next" && carousel.current !== null) {
return (
carousel.current.offsetWidth * currentIndex >= maxScrollWidth.current
);
}
return false;
};
useEffect(() => {
if (carousel !== null && carousel.current !== null) {
carousel.current.scrollLeft = carousel.current.offsetWidth * currentIndex;
}
}, [currentIndex]);
useEffect(() => {
maxScrollWidth.current = carousel.current
? carousel.current.scrollWidth - carousel.current.offsetWidth
: 0;
}, []);
return (
<div className="carousel my-12 mx-auto">
<div className="relative">
<div className="flex justify-between absolute top left w-full h-full">
<button
onClick={movePrev}
className="hover:bg-blue-900/75 text-white w-10 h-full text-center opacity-75 hover:opacity-100
disabled:opacity-25 disabled:cursor-not-allowed z-10 p-0 m-0 transition-all ease-in-out duration-300"
disabled={isDisabled("prev")}
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-12 w-20 -ml-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M15 19l-7-7 7-7"
/>
</svg>
<span className="sr-only">Prev</span>
</button>
<button
onClick={moveNext}
className="hover:bg-blue-900/75 text-white w-10 h-full text-center opacity-75 hover:opacity-100
disabled:opacity-25 disabled:cursor-not-allowed z-10 p-0 m-0 transition-all ease-in-out duration-300"
disabled={isDisabled("next")}
>
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-12 w-20 -ml-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth={2}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M9 5l7 7-7 7"
/>
</svg>
<span className="sr-only">Next</span>
</button>
</div>
<div
ref={carousel}
className="carousel-container relative flex gap-1 scroll-smooth snap-x snap-mandatory touch-pan-x z-0"
>
{data.resources.map((resource, index) => {
return (
<div
key={index}
className="carousel-item text-center relative w-64 h-64 snap-start hover:scale-125 transform-gpu
transition duration-150 ease-in-out"
>
<a
href={resource.link}
className="h-full w-full aspect-square block bg-origin-padding bg-left-top bg-cover bg-no-repeat z-0"
style={{ backgroundImage: `url(${resource.imageUrl || ""})` }}
>
<img
src={resource.imageUrl || ""}
alt={resource.title}
className="w-full aspect-square hidden"
/>
</a>
<a
href={resource.link}
className="h-full w-full aspect-square block absolute top-0 left-0 transition-opacity
duration-300 opacity-0 hover:opacity-100 bg-blue-800/75 z-10"
>
<h3 className="text-white py-6 px-3 mx-auto text-xl">
{resource.title}
</h3>
</a>
</div>
);
})}
</div>
</div>
</div>
);
};
export default CollectionCarousel;
I Want if I click on the edit icon the text will appear in input and I can edit it and when I submit it will edit not created again.
I did the click on edit icon the text will appear in input but when I submit its created as new, so how can I do that?
here is a gif of what I have i want in submit will be updated
app.js
function App() {
const [tasks, setTask]=useState([])
const [title, setTitle]=useState("")
const [changeTasks , setChangeTasks ] = useState(false)
const [edit, setEdit]=useState(false)
useEffect(() => {
axios.get('/tasks')
.then(data=>setTask(data.data))
.catch(err => console.log(err))
}, [changeTasks]);
const addTask = (e) =>{
e.preventDefault()
axios.post('/tasks/create', {title:title, completed: true})
.then(data => setChangeTasks(pre => !pre))
.catch(err => console.log(err))
// to empty input after submit
setTitle("")
if(edit === true){
// do axios.put, but its in other component how could i do that
}
}
return (
<div className="relative flex min-h-screen bg-gray-200 flex-col justify-center overflow-hidden bg-gray-50 py-6 sm:py-12">
<h1 className="flex justify-center p-4 md:p-0 mx-px md:mt-4 md:mb-3 text-center font-extrabold text-transparent text-8xl bg-clip-text bg-gradient-to-r from-purple-800 to-pink-300">
To Do List
</h1>
<div className="relative bg-white px-6 pt-10 pb-8 shadow-xl ring-1 ring-gray-900/5 sm:mx-auto sm:max-w-lg sm:rounded-lg sm:px-10">
<div className="p-2">
<figure className="mb-4">
<blockquote className="italic font-extralight text-slate-700 mb-5">
<q> To-Do lists help us break life into small steps. </q>
<figcaption className="ml-5 text-sm">—Randy Pausch</figcaption>
</blockquote>
</figure>
<form onSubmit={addTask} >
<input
onChange={({target})=>{
setTitle(target.value)
}}
type="text"
className="p-3 mt-2 mb-4 w-full bg-slate-200 rounded border-2 border-slate-200 focus:border-slate-600 focus:outline-none placeholder:italic"
placeholder="Add Your Task..."
value={title}
/>
</form>
<ul>
{tasks.map(ele => <Task {...ele} setChangeTasks = {setChangeTasks} setTitle={setTitle} setEdit={ setEdit}/>)}
</ul>
</div>
</div>
</div>
);
}
export default App;
Task.jsx
import axios from 'axios'
const Task = ({title, id, completed,setChangeTasks, setTitle, setEdit}) => {
const updateTask =()=>{
axios.put(`/tasks/${id}/update`,{title:title,completed : ! completed })
.then(data => setChangeTasks(pre => !pre))
.catch(err => console.log(err))
}
const deleteTask =()=>{
axios.delete(`/tasks/${id}/delete`)
.then(data => setChangeTasks(pre => !pre))
.catch(err => console.log(err))
}
const editTask =()=>{
axios.put(`/tasks/${id}/update`,{title:title})
.then(data => setChangeTasks())
.catch(err => console.log(err))
setEdit(true)
setTitle(title)
}
return (
<li>
<div className="mt-7 ml-3 flex justify-between">
<label className="inline-flex items-center ">
<input
onClick={updateTask}
type="checkbox"
className=" h-6 w-5 accent-violet-200 hover:accent-violet-200 border-0 rounded-md focus:ring-0"
/>
<span className={ completed ? "ml-4 text-lg" : "ml-4 text-lg line-through"} >{title}</span>
</label>
<div className="">
<button onClick={deleteTask} className="mx-4 text-purple-700 hover:text-white hover:bg-purple-600 p-1 px-2 rounded">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeWidth="2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
/>
</svg>
</button>
<button onClick={editTask} class=" text-purple-700 hover:text-white hover:bg-purple-600 p-1 px-2 rounded">
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-5 w-5"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"
/>
</svg>
</button>
</div>
</div>
</li>
)
}
export default Task