Div appear and disappear onclick in React hooks - javascript

I want an effect like this (before onclick)(after oncilck).Just click on which div to make it disappear, and then let the div that disappeared before show again.
Here is the data code(just an array). I want the "show" variable in the data to control whether to display.But I don't know how to implement the destructuring assignment to the array in the click function.
Thank you for your answer!
const leftBarData=
[{
name:"关于音乐",
color:"bg-music-color",
icon:<div className="iconMusicSize">
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
blahblah
</svg>
</div>,
link:"/music",
number:0,
show:true,
},
{
name:"关于编程",
color:"bg-code-color",
icon:<div className="iconSize">
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
blah
</svg>
</div>,
link:"/code",
number:1,
show:true,
},
{
name:"关于设计",
color:"bg-design-color",
icon:<div className="iconSize">
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
blah
</svg>
</div>,
link:"/design",
number:2,
show:false
},
{
name:"关于本人",
color:"bg-about-color",
icon:<div className="iconSize">
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
blah
</svg>
</div>,
link:"/design",
number:3,
show:true
}
]
Here is the map.
const [statusData,setStatusData]=useState(leftBarData)
const changeBar=(pars)=>
{
how to achieve it
}
<div className="flex fixed">
{statusData?.map((index,i)=>(
<Link to={index.link}>
<div className={` ${index.color} ${index.show?"":"hidden"} w-99 h-screen pt-9 `} onClick={()=>changeBar(index)}>
<div className="flex flex-col h-full items-center justify-between">
{index.icon}
<div className="-rotate-90 -translate-y-full mb-10">
<div className="h3 text-white whitespace-nowrap">{index.name}</div>
</div>
</div>
</div>
</Link>
))}
</div>

You can map() your state data to toggle show property of clicked element like this:
const changeBar = pars => {
setStatusData(data => data.map(item => (
item === pars
? {
...item,
show: !item.show
}
: item
)));
};

Related

The JS code for my Tailwind Image Slider won't work :/

I am new to the whole coding topic. For my first "big" project I want to build a simple website with some functionality. I tried to implement an Image slider with Tailwind and JS. But the Code won't work. Thank you for all your help in advance <3screen
HTML and Tailwind:
<section>
<div>
<div class="relativ h-50 relative">
<ul id="slider">
<li class="relativ scale-50">
<img class="h-full w-full object-fill" src="./img/test.png" alt="" />
</li>
<li class="relativ hidden h-[50vh]">
<img class="h-full w-full object-fill" src="./img/logo1.png" alt="" />
</li>
<li class="relativ hidden h-[50vh]">
<img class="h-full w-full object-fill" src="./img/test.png" alt="" />
</li>
</ul>
<div class="absolute top-1/2 -translate-y-1/2 w-full px-5">
<div class="my-auto flex w-full justify-between ">
<button onclick="prev()" class="rounded-full bg-slate-500 bg-opacity-80 p-3 shadow-lg">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-6 w-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" />
</svg>
</button>
<button onclick="next()" class="rounded-full bg-slate-500 bg-opacity-80 p-3 shadow-lg">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="h-6 w-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
</svg>
</button>
</div>
</div>
</div>
</div>
</section>
JS:
// Image slider
currentSlideId = 1;
sliderElement = document.getElementById('slider');
totalSlides = sliderElement.childElementCount;
function next (){
if(totalSlides<currentSlideId){
currentSlideId++;
showSlide();
}
}
function prev(){
if(currentSlideId > 1){
currentSlideId--;
showSlide();
}
}
function showSlide(){
slides = getElementById('slider').getElementsByTagName('li');
for (let index = 0; index < totalSlides; i++){
const element = slide[index];
if(currentSlideId===index+1){
element.classList.remove('hidden')
}else{
element.classList.add('hidden')
}
}
}
I tried to edit my code but it won't work :/
First, welcome to stack overflow.
I think the problem is in the showSlide function inside the for loop, wherein the 'element' variable you wrote:
slide[index]
But I think it should be:
slides[index]
Because there is no variable in that name.
And also like #BestCoderBoy commended, it's always good to initialize a variable before using it, and it looks like you're using getElementByID without the document.

Create click event on newly appended buttons with JQuery

I want to create alerts that can be hidden, but when I hide one, they are all hidden at the same time.
This is the code I have, where I need to create the "click" event to hide only the newly created button but hide all of them at the same time:
const newAlert = $("#mainBodyContainer").append(`
<div class="alert alert-info shadow-lg p-2 mt-2">
<p>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
class="stroke-current flex-shrink-0 w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
<span>a</span>
</p>
<strong class="text-xl align-center cursor-pointer alert-del">×</strong>
</div>
`);
const deleteAlertButton = newAlert.find(".alert-del")
deleteAlertButton.on("click", () => {
deleteAlertButton.parent().addClass("hidden");
});
Docs jQuery find: "Get the descendants of each element in the current set of matched elements"
Keyword: elementS.
You don't have a unique selector. Every time you create a new button, your event handler returns ALL .alert-del classes it finds inside #mainBodyContainer. Including the ones already in there.
To solve the issue, make sure each button can be uniquely selected:
let alerts = 1;
function createAlert()
{
const newAlert = $("#mainBodyContainer").append(`
<div class="alert alert-info shadow-lg p-2 mt-2">
<p>
<span>Button ${alerts}</span>
</p>
<strong id="alert_${alerts}" class="text-xl align-center cursor-pointer alert-del">×</strong>
</div>
`);
const deleteAlertButton = $("#alert_"+alerts);
deleteAlertButton.on("click", () => {
deleteAlertButton.parent().addClass("hidden");
});
alerts++;
}
createAlert();
createAlert();
createAlert();
.hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="mainBodyContainer"></div>

React Redux update component after set like

I need to update my component after user set like, what methods should I use for this? I m newbie in react-redux and even dont know some basics things.
I also have redux-thunk in my project but im even don`t know how to use it for async responses.
PostCard code.
import * as React from "react";
//Redux
import { useDispatch } from "react-redux";
import { likePostById } from "../Redux/Slice/PostSlice";
import { GetPostByInterests } from "../Redux/Slice/PostSlice";
export const PostCard = (props) => {
const posts = props.posts;
const dispatch = useDispatch();
const LikePost = (id, is_user_liked) => {
const is_liked = !is_user_liked;
dispatch(likePostById(id, is_liked))
}
return (
<div className="flex bg-white shadow-lg rounded-lg mx-4 md:mx-auto max-w-md md:max-w-2xl mt-2">
<div className="flex items-start px-4 py-6">
<img
className="w-12 h-12 rounded-full object-cover mr-4 shadow"
src={posts?.author.avatar.url}
alt="avatar"
></img>
<div className="">
<div className="flex items-center justify-between">
<h2 className="text-lg font-semibold text-gray-900 -mt-1">
{posts.author.first_name} {posts.author.last_name}
</h2>
<small className="text-sm text-gray-700">{}</small>
</div>
<p className="mt-3 text-gray-700 text-sm">{posts.text}</p>
<div className="mt-4 flex items-center">
<div className="flex mr-2 text-gray-700 text-sm mr-3">
{posts.is_user_liked ? (
<svg
fill="#f01616"
viewBox="0 0 24 24"
className="w-4 h-4 mr-1"
stroke="currentColor"
onClick={() => {LikePost(posts.id, posts.is_user_liked)}}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
/>
</svg>
) : (
<svg
fill="none"
viewBox="0 0 24 24"
className="w-4 h-4 mr-1"
stroke="currentColor"
onClick={() => {LikePost(posts.id, posts.is_user_liked)}}
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
/>
</svg>
)}
<span>{posts.likes_count}</span>
</div>
<div className="flex mr-2 text-gray-700 text-sm mr-8">
<svg
fill="none"
viewBox="0 0 24 24"
className="w-4 h-4 mr-1"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M17 8h2a2 2 0 012 2v6a2 2 0 01-2 2h-2v4l-4-4H9a1.994 1.994 0 01-1.414-.586m0 0L11 14h4a2 2 0 002-2V6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2v4l.586-.586z"
/>
</svg>
<span>{posts.comments_count}</span>
</div>
</div>
</div>
</div>
</div>
);
};
export default PostCard;
Redux PostSlice
Server Post answer
id(pin): 143
text(pin): "some text"
topic(pin): "ANDROID_DEVELOPMENT"
publish_time(pin): "2022-06-02T23:28:18.415933"
is_user_liked(pin): true
likes_count(pin): 2
comments_count(pin): 0
const initialState = {
posts: [],
};
const post = createSlice({
name: "post",
initialState,
reducers: {
getPosts(state, action) {
state.posts = action.payload.posts;
},
likePost(state, action){
state.posts.is_user_liked = action.payload.is_user_liked;
},
},
});
const { likePost } = post.actions;
export function likePostById(id, is_liked) {
return async (dispatch) => {
try {
await API.post("/posts/" + id + "/like", null, {
params: {
is_liked: is_liked,
},
});
dispatch(
likePost({
is_user_liked: !is_liked,
})
)
} catch (e) {
console.log(e);
}
};
}

How to un-string an HTML tag block to be rendered in React code?

I want to use an HTML tag as a value in my React code, inside the map function. However, React renders it as a string. I want it to be rendered as HTML or SVG.
skills: [
{
icon: `<svg xmlns="http://www.w3.org/2000/svg" className="inline-block h-16 w-16 fill-current text-mygreen" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1} d="M15 15l-2 5L9 9l11 4-5 2zm0 0l5 5M7.188 2.239l.777 2.897M5.136 7.965l-2.898-.777M13.95 4.05l-2.122 2.122m-5.657 5.656l-2.12 2.122" />
</svg>`,
category: 'Front-end',
}
//I Want to use it in the map function so that it renders the actual SVG icon:
data.skills.map(skill => {
return (<div className="">
{skill.icon}
<div className="mt-4 md:mt-8 text-2xl text-gray-800 font-bold font-Titillium">{skill.category}</div>
})
However, it renders the SVG as a string. How do I fix that?

How can I add style to the active tab in sidenav using state

I am making a side nav for which I need to add the left border to the current tab How can I achieve this using state by passing a boolean value to the Child SideNavItem class as a prop and the change it on every tab change.
Here is My code for the parent SideNav class
Here I am using an if-else condition to check for the current location and the pass that is a prop to the Child class. But Right now both the Home and My Profile is getting the side border.
import { NavLink } from "react-router-dom";
import SideNavItems from "./SideNavItems";
import React, {useState} from 'react';
const HomeIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
/>
</svg>
);
const ProfileIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"
/>
</svg>
);
const PointIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.784-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z"
/>
</svg>
);
const SupportIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z"
/>
</svg>
);
const ContributeIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
className="h-8 w-6"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
/>
</svg>
);
const SideNav = (): JSX.Element => {
let [active, setActive] = useState(true);
let isActive = (currentPath: any, thisPath: any) => {
if (currentPath===thisPath) {
setActive(true)
} else {
setActive(false);
}
return active;
}
const resetState = () => {
setActive(false);
};
return (
<div className="sidebar mt-5">
<div className="logo ml-2">
<img
alt="logo"
src={require("../assets/images/logo.png").default}
/>
</div>
<NavLink to="/"><SideNavItems active={() => isActive(window.location.pathname, "/")} icon={HomeIcon} text={"Home"}/></NavLink>
<NavLink to="/profile"><SideNavItems active={() => isActive(window.location.pathname, "/profile")} icon={ProfileIcon} text={"My Profile"}/></NavLink>
<SideNavItems active={""} icon={PointIcon} text={"Daily Points"}/>
<SideNavItems active={""} icon={SupportIcon} text={"Support"}/>
<SideNavItems active={""} icon={ContributeIcon} text={"Contribute"}/>
</div>
);
};
export default SideNav;
Here is the code for Child Class
import React from "react";
type Props = {
active: any;
text: string;
icon: any;
};
const SideNavItems: React.FC<Props> = ({active, icon, text }) => (
<div className={`flex items-center cursor-pointer hover:text-red-400 transition duration-100 ease-in-out ${active ? ` text-red-400 border-l-4 border-red-400` : ``}`}>
<div className="icon p-5">{icon}</div>
<h2 className="font-extrabold text-xl mr-5">{text}</h2>
</div>
);
export default SideNavItems;
Part of the confusion you're facing here is due to the fact that calling setActive in the isActive function doesn't immediately change the value of the active variable, and since you are returning the active variable immediately, you are actually returning the previous value active, not the intended value.
In fact, you probably don't need to save the value of active in a component state variable:
const SideNav = (): JSX.Element => {
return (
<div className='sidebar mt-5'>
<div className='logo ml-2'>
<img alt='logo' src={require('../assets/images/logo.png').default} />
</div>
<NavLink to='/'>
<SideNavItems
active={window.location.pathname === '/'}
icon={HomeIcon}
text={'Home'}
/>
</NavLink>
<NavLink to='/profile'>
<SideNavItems
active={window.location.pathname === '/profile'}
icon={ProfileIcon}
text={'My Profile'}
/>
</NavLink>
<SideNavItems active={''} icon={PointIcon} text={'Daily Points'} />
<SideNavItems active={''} icon={SupportIcon} text={'Support'} />
<SideNavItems active={''} icon={ContributeIcon} text={'Contribute'} />
</div>
);
};
export default SideNav;
or if you're using react router, you can use the useLocation hook to make sure the component always re-renders when the path changes:
import { useLocation } from 'react-router-dom';
const SideNav = (): JSX.Element => {
const { pathname: currentPath } = useLocation();
return (
<div className='sidebar mt-5'>
<div className='logo ml-2'>
<img alt='logo' src={require('../assets/images/logo.png').default} />
</div>
<NavLink to='/'>
<SideNavItems
active={currentPath === '/'}
icon={HomeIcon}
text={'Home'}
/>
</NavLink>
<NavLink to='/profile'>
<SideNavItems
active={currentPath === '/profile'}
icon={ProfileIcon}
text={'My Profile'}
/>
</NavLink>
<SideNavItems active={''} icon={PointIcon} text={'Daily Points'} />
<SideNavItems active={''} icon={SupportIcon} text={'Support'} />
<SideNavItems active={''} icon={ContributeIcon} text={'Contribute'} />
</div>
);
};
export default SideNav;

Categories

Resources