React Recharts tooltip not showing proper data - javascript

I have two lines plotted on a recharts one is plotting everyday and the other is plotting once every quarter. The recharts tooltip only shows up for the pink line when it is directly hovered over the plotted point and says 0 when it is not over the directly plotted point. I want the tooltip to always show the data during that time. I tried adding in the "filterNull={false}" into the tooltip but it did not work. Any Ideas?
<Tooltip content={renderTooltipContentGeneric} filterNull={false} />
export const renderTooltipContentGeneric = o => {
const { payload, label } = o
const total = payload?.reduce((result, entry) => result + entry.value, 0)
return (
<div className="customized-tooltip-content-core">
<div className="list">
{payload?.map((entry, index) => (
<div
className="listItem"
key={`item-${index}`}
style={{
color: entry.color,
display: 'flex',
flexDirection: 'row',
gap: '4px',
}}
>
<div style={{ color: 'var(--white)' }}>{`${moment(label).format(
'lll'
)}: `}</div>
{`${numeral(entry.value).format('0.000 a')} `}
</div>
))}
</div>
</div>
)
}

Related

Update scroll so that cursor remains with the dragged item when new items are added

I have a list of items in a scrollable div (overflow-y: scroll). When I start dragging (in the real website I am using react-beautiful-dnd) some of the items will expand to show subitems since they are dropdown. This causes the position of the items to shift down and so the item that I was dragging moves downwards but my cursor remains in the same position.
Here's the link to the problem: https://codesandbox.io/s/gracious-einstein-vvsbtp?file=/src/App.js
import { useState } from "react";
export default function App() {
const [show, setShow] = useState(false);
const handleDrag = () => {
setShow(true);
};
const DisplayHello = () => {
return (
<>
{new Array(5).fill(0, 0, 5).map((ele, index) => {
return (
<p style={{ margin: "5px" }} key={index}>
Hello
</p>
);
})}
</>
);
};
return (
<div className="App" style={{ height: "400px" }}>
<div
style={{
display: "flex",
flexDirection: "column",
height: "100%",
border: "1px solid red",
width: "200px",
overflow: "scroll"
}}
>
<DisplayHello />
{show && <DisplayHello />}
<div
style={{ backgroundColor: "dodgerblue" }}
draggable="true"
onDrag={handleDrag}
>
Drag Me
</div>
{show && <DisplayHello />}
<DisplayHello />
</div>
</div>
);
}
What I want is that even if the items expand, the cursor should remain on the draggable item. Is this even possible?

I am trying to align movieCards side by side. But they are aligning in a column

This is my movie list component. I tried different attributes in the div section to get the cards in a row. But all the cards are aligned in a column.should i use either flex or grid.If yes how can i use them. Even i referred to many resources for this.But didn't worked for me. What should I do to get the cards as I wish . Please assist me.
import React, { useState } from 'react'
import { useSelector } from 'react-redux'
import MovieCard from './MovieCard'
const MoviesList = (props) => {
const [search, setSearch] = useState('')
const [filterBy, setFilterBy] = useState([])
const [orderBy, setOrderBy] = useState('')
const movies = useSelector((state) => {
console.log(state.movies)
return state.movies
})
const handleChange = (e) => {
const inputValue = e.target.value
setSearch(inputValue)
const filteredValue = movies.filter((movie) => {
return movie.Title.toLowerCase().includes(inputValue)
})
setFilterBy(filteredValue)
console.log(filteredValue)
}
const handleSelectChange = (e) => {
setOrderBy(e.target.value)
}
const show = (movies) => {
switch (orderBy) {
case 'a-z': return [...movies.sort((a, b) => a.Title.localeCompare(b.Title))]
case 'z-a': return [...movies.sort((a, b) => b.Title.localeCompare(a.Title))]
case '1-100': return [...movies.sort((a, b) => a.imdbRating - b.imdbRating)]
case '100-1': return [...movies.sort((a, b) => b.imdbRating - a.imdbRating)]
default: return [...movies]
}
}
return (
<div className='container'>
<div className='d-flex mb-3 '>
<h1 style={{ textAlign: 'center', border: 'solid lightgreen', backgroundColor: 'white' }} >My Movie List</h1>
<form style={{ float: 'right', marginRight: '35px' }}>
<input type="text" placeholder='search by name' value={search} onChange={handleChange} />
<select value={orderBy} onChange={handleSelectChange} >
<option value="">orderBy</option>
<option value="a-z">a-z</option>
<option value="z-a">z-a</option>
<option value="1-100">1-100</option>
<option value="100-1">100-1</option>
</select>
</form>
</div>
<div className=" row pt-2 justify-content-around " style={{ textAlign: 'center', width: '100%' }}>
{
filterBy.length > 0 ? (
filterBy.map((movie) => {
return <MovieCard key={movie.imdbID} Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} />
})
) : (
show(movies).map((movie) => {
return <MovieCard key={movie.imdbID} {...movie} />
})
)
}
</div>
</div >
)
}
export default MoviesList
And this is Movie card component
import React from 'react'
import { useDispatch } from 'react-redux'
import { removeMovie } from '../actions/moviesAction'
const MovieCard = (props) => {
console.log(props)
const { Title, Poster, imdbRating, imdbID } = props
const dispatch = useDispatch()
return (
<div className="card mt-2 p-2 bd-highlight border shadow rounded" style={{ width: '16rem' }}>
<img className="card-img-left pt-2" src={Poster} alt={Title} style={{ width: '200px', height: '200px' }} />
<div className="card-body">
<h4 className="card-title">Name : {Title}</h4>
<h5 className="card-title">Ranking : #{imdbRating}</h5>
<ion-icon name="trash" style={{ color: 'red' }} onClick={() => {
dispatch(removeMovie(imdbID))
}}>
</ion-icon>
</div>
</div>
)}
export default MovieCard
Please help me to resolve this. Thankyou
Try providing display: flex, to the div rendering MovieCard, like this:
<div className=" row pt-2 justify-content-around "
style={{ textAlign: 'center', width: '100%', display: 'flex' }}>
{
filterBy.length > 0 ? (
filterBy.map((movie) => {
return <MovieCard key={movie.imdbID} Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} />
})
) : (
show(movies).map((movie) => {
return <MovieCard key={movie.imdbID} {...movie} />
})
)
}
</div>
You can just use flex here.
add the below code to your parent div (div containing all the cards).
If you have a css file add a class to that div and add the following styles.
display: flex;
flex-wrap: wrap;
justify-content: center;
or if you want to use inline styling do the following:
<div className=" row pt-2 justify-content-around " style={{ textAlign: 'center', width: '100%', display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
{filterBy.length > 0 ? (
filterBy.map((movie) => {
return <MovieCard key={movie.imdbID} Poster={movie.Poster} Title={movie.Title} imdbRating={movie.imdbRating} imdbID={movie.imdbID} />
})
) : (
show(movies).map((movie) => {
return <MovieCard key={movie.imdbID} {...movie} />
}
)
)}
</div>
Try using a grid method something like the code below will allow you control the number of rows and columns you want as well as size them.
**
<h1>Example { grid-template-rows: 40% 50% 50px;}</h1>
<p><strong style="color: red">The shorthand property, grid-template, can replace both </strong>grid-template-rows and grid-template-columns.</p>
<hr>
<p style="font-family: Courier">When using grid-template, the values before the slash will determine the size of each row. The values after the slash determine the size of each column. </p><hr>
<p style="font-family: Courier">In this example there are 3 rows and 3 columns added to the grid.</p><h1>Example {grid-template: 40% 50% 50px/100px 50% 200px;}</h1><br>
<p><strong style="color: red">By using the (fr) unit, we can define the size of columns and rows as a fraction of the grid’s length and width.</strong><br>Using (fr) makes it easier to prevent grid items from overflowing the boundaries of the grid.</p>
<h1>Example {grid-template: 1fr 1fr 1fr / 3fr 50% 1fr;}<br> width: 400px;<br>
**
If you're using Bootstrap then you don't need to use flex nor grid directly. This is the Bootstrap's way to achieve the desired layout:
<div className="row">
{movies.map(item => (
<div className="col">
// then here yo can put your card for the movie
</div>
))}
</div>
This is the Bootstrap doc about it

React Recharts: Design custom tooltip

I am trying to replace recharts default tooltip with custom tooltip.
The existing tooltip looks like this.
I wanted to replace the above default tooltip as
I made sandbox for the code.
Thanks
Very quick solution. You can alter it as you want
Create a custom tooltip class
export const CustomTooltip = ({ active, payload, label }) => {
if (active && payload && payload.length) {
return (
<div className="custom-tooltip">
<p className="label">{`${label} : ${payload[0].value}`}</p>
<div>
{payload.map((pld) => (
<div style={{ display: "inline-block", padding: 10 }}>
<div style={{ color: pld.fill }}>{pld.value}</div>
<div>{pld.dataKey}</div>
</div>
))}
</div>
</div>
);
}
return null;
};
And use it like this
<Tooltip content={<CustomTooltip />} cursor={{ fill: "transparent" }} />
demo

How can I position button dynamatically according to page components?

In React application I am displaying list of images. When individual book is removed Hide Books button takes the place to that component.
What I am trying to achieve is Hide Books button should remain at the same position and should dynamatically change its position on y axis if whole row of books is deleted
Initial state of application
When individual book is removed -
app.js
return(
<div style={{ position: "relative", minHeight: "100vh" }}>
<button
style={{
position: "absolute",
bottom: "",
}}
onClick={clearBooks}
>
Hide Books
</button>
</div>
)
could you share more of your code? maybe have a codesandox example? It seems to be a styling issue but it's hard to tell without more code.
-edit-
your button should be separated from your list of books, this is the reason why it essentially "follows" your last book card.
Try to do something like this
return (
<section className='wrapper'>
<div className='bookList'>
{booksData.map(book => {
//code your books here
}
</div>
//then put your button out of the div
<button onClick={function}>hide books</button>
</section>
)
your CSS for the wrapper div could be something like this
.wrapper{
display: flex;
flex-direction: column
}
this way you'll have the books first then the button will be displayed below the list
Place the button as the next sibling to the section of Books. Shown in the following. All I did was to move the button out of the section. You will have to style the button with padding and such for the updated layout.
// in index.js, BookList
return (
<>
<section className="booklist">
{booksData.map((book, index) => {
return (
<Book
key={index}
{...book}
removeIndividualBook={removeIndividualBook}
></Book>
);
})}
</section>
{booksData.length === 0 ? (
<button onClick={handleShowBook}>Show Books</button>
) : (
<div style={{ position: "relative", minHeight: "100vh" }}>
<button
style={{
// position: "absolute",
// marginTop: "2350px",
// marginLeft: "28px",
position: "absolute",
//left: "12%",
bottom: "",
}}
onClick={clearBooks}
>
Hide Books
</button>
</div>
)}
</>
);

React map to render with row

Hi I have an array with 6 element and itterate 3 in each row with map function by dividing the array into three elements and I dont do this without dividing array my code is below
<div
style={{
width: "100%",
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
}}
>
{array1.map((item, index) => {
return (
<div className="col-4">
<img src={item.icon} />
<p >{item.title}</p>
<p >
{item.description}
</p>
</div>
);
})}
</div>
<div
style={{
width: "100%",
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
}}
>
{array2.map((item) => {
return (
<div className="col-4 item-item">
<img src={item.icon} />
<p>{item.title}</p>
<p>
{item.description}
</p>
</div>
);
})}
</div>
I want to map 3 elements per row and without dividing the 6 elements array to 3 elements thanks for suggestion
You can just use map for this purpose
array.map((element, index) => {
if (index % 3 === 0)
return (
<div className="row">
<div className="col">{array[index]}</div>
<div className="col">{array[index + 1]}</div>
<div className="col">{array[index + 2]}</div>
</div>
);
})
If you decide to change number of elements per row, you can just tweak the values.
Check a working example here
I'd recommend you use this function here to split the array up into chunks. From there you can perform a nested map!
// # Source https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/chunk.md
const chunk = (arr, size) =>
Array.from({ length: Math.ceil(arr.length / size) }, (v, i) =>
arr.slice(i * size, i * size + size)
);
console.log(chunk([1, 2, 3, 4, 5,6], 3));
// Output - [[1,2,3],[4,5,6]]
Considering you already know the length of array which is 6. Assuming array name to be "originalArray"
<div
style={{
width: "100%",
display: "flex",
flexWrap: "wrap",
justifyContent: "space-around",
}}
>
{originalArray.map((item, index) => {
(index<3)?
return (
<div className="col-4">
<img src={item.icon} />
<p >{item.title}</p>
<p >
{item.description}
</p>
</div>
}
: return( <div className="col-4 item-item">
<img src={item.icon} />
<p>{item.title}</p>
<p>
{item.description}
</p>
</div>)
);
})}
</div>
I am not sure about performance of this snippet, but you can achieve what you want with reduce instead of map
array.reduce<JSX.Element[]>((rows, item, itemIndex) => {
const ComponentToRender = <Component />
if (itemIndex % 3 === 0) {
rows.push(<Row key={rows.length + 1}>{ComponentToRender}</Row>);
} else {
const LastRow = rows[rows.length - 1];
const cols = [
...React.Children.toArray(LastRow.props.children),
ComponentToRender,
];
rows[rows.length - 1] = <Row key={rows.length + 1}>{cols}</Row>;
}
return rows;
}, [])
Or just use a CSS grid system to be able to render 3 elements per row. That way you can stick to the simple map.

Categories

Resources