react dom traverself or parent div targeting? - reactjs

I have the following in React (using redux):
....
deleteBase(title) {
this.props.dispatch(removeBase(title));
}
render() {
const baseList = this.props.bases.map(base => {
return (
<li key={base.title} className="base">
<Link to={base.title}>{base.title}</Link>
<i
className="fas fa-times"
onClick={title => this.deleteBase(title)}
/>
</li>
);
});
}
In the dispatch function of removeBase I will need to have access to the single base.title from the clicked element. No matter how I try to get the right title transferred over to the function I can't do it.
return (
<ul className="baseWrapper">
{baseList}
<li className="add-list-wrapper">
<AddBase type="base" onAdd={title => this.addBase(title)} />
</li>
</ul>
);

Related

Vertical menu in react

I need to have a vertical menu like below picture, in react
here is my code:
function DropDownMenu({className}) {
const [isOpen, setIsopen] = useState(false);
const toggleDropDown = () => {
setIsopen(isOpen => !isOpen)
}
return (
<nav className={styles.nav}>
<ul>
<li onClick={toggleDropDown} ><a href='#settings'>item1</a>
{isOpen && <ul>
<li><a href='#settings'>sub-item1</a></li>
<li><a href='#settings'>sub-item2</a></li>
<li><a href='#settings'>sub-item-3</a></li>
</ul>
}
</li>
<li onClick={toggleDropDown} ><a href='#message'>item3</a>
{isOpen &&
<ul>
<li><a href='#settings'>sub-item1</a></li>
<li><a href='#settings'>sub-item2</a></li>
</ul>
}
</li>
</ul>
</nav>
);
}
It lacks hide/show each item separately, and an arrow with some animation when it opens/closes
You should create a separate component called MenuItem and isolate the toggle logic.
const MenuItem = ({ menuTitle, subMenus = [] }) => {
const [isOpen, setIsopen] = useState(false);
const toggleDropDown = () => {
setIsopen((isOpen) => !isOpen);
};
return (
<li onClick={toggleDropDown}>
{menuTitle}
{isOpen && (
<ul>
{subMenus.map((item) => (
<li>
{item}
</li>
))}
</ul>
)}
</li>
);
};
Then use MenuItem in DropDownMenu
function DropDownMenu({ className }) {
return (
<nav>
<ul>
<MenuItem
menuTitle="item1"
subMenus={["sub-item1", "sub-item2", "sub-item-3"]}
/>
<MenuItem menuTitle="item3" subMenus={["sub-item1", "sub-item2"]} />
</ul>
</nav>
);
}
Code sandbox

React render instagram feeds and loop comments/likes

I"m trying to render comments with likes and loop them. please see image on demo.
All of this comes form data.json
How can I loop all comments? I have only one displayed. What am I missing here?
Sorry I'm trying my best here with react as I'm quite a beginner.
my index.js
import React from "react";
import styles from "./styles";
const Posts = (props) => {
const { data } = props;
const comments = data.edge_media_to_comment.edges[0].node.text
const locationName = data.location.name
const username = data.owner.username
const id = data.id
const url = `https://www.instagram.com/${data.owner.username}`
const likes = data.edge_media_preview_like.count
return (
<>
<a href={url} rel="noopener noreferrer" target="_blank" key={id}>
<img src={data.owner.profile_pic_url} />
</a>
<span>{locationName}</span>
<a href={url} rel="noopener noreferrer" target="_blank" key={id}>#{username}</a>
<p>{username}</p>
<hr />
<ul>
<li>
{comments !== null ? comments.toLocaleString() : 0}
</li>
<li className="post-item-likes">
{likes !== null ? likes.toLocaleString() : 0}
</li>
</ul>
<hr />
</>
);
};
export default Posts;
In your Post component need to use data.comments from props and use .map
method for render multiple comments instead of comments.toLocaleString()
Example:
import React from "react";
const Posts = (props) => {
const { data } = props;
console.log('007',data);
return (
<>
<img src={data.owner.profile_pic_url} />
<span>{data.location.name}</span>
<a href="" target="_blank">
#{data.owner.username}
</a>
<p> {data.owner.username}</p>
<hr />
<div>
{data?.comments?.map(comment => {
return (<div>
{comment?.text} - {comment?.likeCount}
</div>)
})}
</div>
</>
);
};
export default Posts;
You need to map through the comments array and for each comment return the text and likes.
Declare comments - below const { data } = props;:
const comments = data.comments;
In return add this:
<ul>
{comments.map((comment) => (
<li>
{comment.text} - {comment.likeCount}
</li>
))}
</ul>

React Cannot read property of undefined - Array.map (<anonymous>)

I am fetching data from api and importing the data in the WeatherData.js and passing it as a prop to SmallWeatherCard.js because I want to pass it to another component too later on.
when I do console.log(data) in SmallWeatherCard.js I can see the whole data in the console but when trying to map it I get an error "Cannot read property of undefined"
What am I doing wrong here?
all the code here: Codesanbox
import React from "react";
export const SmallWeatherCard = ({ data }) => {
return (
<div>
{data.properties.timeseries.map((i, index) => (
<div>
<ul key={index}>
<li> {i.data.next_6_hours.summary.symbol_code}
</li>
<li>
{Math.round(i.data.next_6_hours.details.air_temperature_min)}°
</li>
<li>|</li>
<li>
{Math.round(i.data.next_6_hours.details.air_temperature_max)}°
</li>
</ul>
</div>
))}
</div>
);
};
Your probably using this kinda api. So, the error is api doesn't always return all fields. For example in my case i.data.next_6_hours wasn't defined.
So, try something like this,
export const SmallWeatherCard = ({ data }) => {
console.log(typeof data);
return (
<div>
{data.properties.timeseries.map(
(i, index) =>
i.data.next_6_hours != null && (
<div>
<ul key={index}>
<li>
{Math.round(i.data.next_6_hours.details.air_temperature_min)}°
</li>
<li>|</li>
<li>
{Math.round(i.data.next_6_hours.details.air_temperature_max)}°
</li>
</ul>
</div>
)
)}
</div>
);
};
Using CodeSandbox.

Hiding an element after a while in Next.js

I have a header component as a function component. I want show a popup when logo text is clicked. After for a time it should close automatically. I use hooks for state of popup. But set state function doesn't work in setTimeout function. How can fix this?
import Link from 'next/link'
import style from './header.module.css'
const Header = () => {
const [popupOpen, setPopupOpen] = React.useState(false)
return (
<header className={style.header}>
<nav className={style.nav}>
<div
className={style.popupContainer}
onClick={() => {
setPopupOpen(!popupOpen)
console.log(popupOpen)
setTimeout(() => {
console.log(popupOpen)
setPopupOpen(!popupOpen)
console.log(popupOpen)
}, 1000)
}}
>
<span className={style.logo}>Logo</span>
<span
className={`${style.popupText} ${
popupOpen ? style.show : style.hide
}`}
>
Popup Text
</span>
</div>
<ul className={style.ul}>
<li>
<Link href='/'>
<a>.home</a>
</Link>
</li>
<li>
<Link href='/contact'>
<a>.contact</a>
</Link>
</li>
</ul>
</nav>
</header>
)
}
export default Header
Console log:
Let me suggests, this is the same question as:
React - useState - why setTimeout function does not have latest state value?
const _onClick = () => {
setPopupOpen(!popupOpen);
setTimeout(() => {
setPopupOpen(popupOpen => !popupOpen)
}, 2000);
};
Its happening because setPopupOpen is asynchronous. So by the time setPopupOpen(!popupOpen) is called it has same value as onClick first setPopupOpen(!popupOpen) so eventually when it called both setPopup doing same state update i.e both updating as false. Better way is to usesetPopupOpen callback function to update the value. I added this code.
import { useState } from "react";
import Link from "next/link";
import style from "./style.module.css";
const Header = () => {
const [popupOpen, setPopupOpen] = useState(false);
const toggle = () => {
setPopupOpen((prev) => !prev);
};
const onClick = () => {
setPopupOpen(!popupOpen);
setTimeout(() => {
toggle();
}, 1000);
};
return (
<header className={style.header}>
<nav className={style.nav}>
<div className={style.popupContainer} onClick={onClick}>
<span className={style.logo}>Logo</span>
{popupOpen && (
<span
className={`${style.popupText} ${
popupOpen ? style.show : style.hide
}`}
>
Popup Text
</span>
)}
</div>
<ul className={style.ul}>
<li>
<Link href="/">
<a>.home</a>
</Link>
</li>
<li>
<Link href="/contact">
<a>.contact</a>
</Link>
</li>
</ul>
</nav>
</header>
);
};
export default function IndexPage() {
return (
<div>
<Header />
</div>
);
}
Here is the demo: https://codesandbox.io/s/pedantic-haibt-iqecz?file=/pages/index.js:0-1212

can't use the Refs properly in react js, Cannot read property of undefined

I am very new to react and js,
I have a menu and submenu, I use a list to map data,
I want to write a function, so onmouseover one item in the list,
if it has submenu, it will show.
the problem is that I can't select the submenu using ref.
It is just too complicated for me, any help would be much appreciated!
enter image description here
import React, { Component } from "react";
export class Menu extends Component {
constructor(props) {
super(props);
this.liRefs = [];
}
showSubmenu = (e) => {
// this.liRefs.current.style.display = "block";
for (var i = 0; i < this.liRefs.length; i++) {
this.liRefs[i].current.style.display = "block";
}
// console.log(this.liRefs[10]);
};
getStyle = (e) => {
e.target.style.background = "red";
};
render() {
return (
<ul className="mainmenu">
{this.props.items.map((i) =>
i.subitems ? (
<li key={i.id} onMouseOver={this.showSubmenu}>
{i.icon}
{i.name}
<ul key={i.id} ref={(ref) => (this.liRefs[i.id] = ref)}>
{i.subitems.map((item) => (
<div key={item.id} className="submenu">
{item.icon}
{item.name}
</div>
))}
</ul>
</li>
) : (
<li key={i.id}>
{i.icon}
{i.name}
{i.img}
</li>
)
)}
</ul>
);
}
}
export default Menu;
You are giving ref value to this. liRefs[i.id] and accessing through this. liRefs[i] so that both are the different change your code as below:
{this.props.items.map((i,index) =>
i.subitems ? (
<li key={i.id} onMouseOver={this.showSubmenu}>
{i.icon}
{i.name}
<ul key={i.id} ref={(ref) => (this.liRefs[i.id] = ref)}>
{i.subitems.map((item) => (
<div key={item.id} className="submenu">
{item.icon}
{item.name}
</div>
))}
</ul>
</li>
) : (
<li key={i.id}>
{i.icon}
{i.name}
{i.img}
</li>
)
)}

Resources