I am using nuka carousel in react TypeScript a saleor pwa react ts app
Nuka carousel not showing items cause nuka is passing slideHeight 0 to slider -frame
Code Example:
render() {
const { title } = this.props;
const { products } = this.state;
const productsList = products.map((product: any) => (
<Link to={'/product/' + product.id} key={product.id}>
<ProductListItem product={product} />
</Link>
))
return (
<div className="products">
<div className="container">
<h3>{title}</h3>
<Carousel>
{productsList}
</Carousel>
</div>
</div >
)
}
I solve it by just add if (products.length)
Solution:
render() {
const { title } = this.props;
const { products } = this.state;
if (products.length) {
const productsList = products.map((product: any) => (
<Link
to={'/product/' + product.id} key={product.id}
>
<ProductListItem product={product} />
</Link>
))
return (
<div className="products">
<div className="container">
<h3>{title}</h3>
<Carousel>
{productsList}
</Carousel>
</div>
</div >
)
}
return null;
}
There is no need to override css this is proper way
Here is solution Via Override css. this is for those who is interested in css override
Related
I've got a set of dashboards that display in bootstrap cards on a front page and I would like to wrap them in a div with the class row for every 3rd entry. I was thinking about marking my dashboard component with the DB id from props and use a modulus function, but that will cause problems if an ID is deleted
Dashboard component:
export type DashboardProps = {
id: number
title: string
description: string
}
const Dashboard: React.FC<{ dashboard: DashboardProps }> = ({ dashboard }) => {
return (
<>
<div className="col-sm-12 col-lg-4">
<div className="card bg-light h-100">
<div className="card-header">
{dashboard.title}
</div>
<div className="card-body d-flex flex-column">
<p className="card-text">
{dashboard.description}
</p>
<a className="btn btn-info text-center mt-auto"
onClick={() =>
Router.push("/dashboard/[id]", `/dashboard/${dashboard.id}`)
}
>Go to dashboard</a>
</div>
</div>
</div>
</>
)
}
export default Dashboard
Index page:
type Props = {
dashboards: DashboardProps[]
}
export const getServerSideProps: GetServerSideProps = async () => {
const dashboards = await prisma.dashboard.findMany({
orderBy: { id: "asc", },
})
return {
props: JSON.parse(JSON.stringify({ dashboards })),
}
}
const Index: React.FC<Props> = (props) => {
const { data: session, status } = useSession()
if (status === "loading") {
return (
<Spinner />
)
}
if (!session) {
return (
<Layout>
<AccessDenied />
</Layout>
)
}
return (
<Layout>
<h1>Dashboards</h1>
{props.dashboards.map((dashboard) => (
<Dashboard dashboard={dashboard} />
))}
</Layout>
)
}
export default Index
I could also potentially wrap them in a single div with class row, but I would need to enforce a top/bottom margin so the cards don't stack right on top of each other. Any tips to get me rolling on this would be greatly appreciated!
.map provides index, you this to find every 3rd element.
//...
{
props.dashboards.map((dashboard, index) =>
(index + 1) % 3 === 0 ? (
<div>
<Dashboard key={dashboard.id} dashboard={dashboard} />
</div>
) : (
<Dashboard key={dashboard.id} dashboard={dashboard} />
)
)
}
this is one of my pages in react app and it shows everything ok:
const showAllFavorite = (props) => {
const [favorites, setFavorites] = useState([]);
useEffect(async () => {
const resp = await generalGet({}, '/favorite');
setFavorites(resp.data);
}, [])
return(
<React.Fragment>
<MainMenu title="favorites" history={props.history}/>
<div className="container mt-4">
<div className="d-flex flex-wrap">
{
favorites.map(fav => (
<div style={{flex: '50%'}}>
<Link
to={`/recipe/${fav.id}`}
key={fav.id}
>
<FoodItem
className="foodItem"
name={fav.name}
cover={fav.cover}
width={'auto'}
/>
</Link>
</div>
))
}
</div>
</div>
</React.Fragment>
)
}
export default showAllFavorite;
but when I want to code like this it doesn't show anything :
const showAllFavorite = (props) => {
const [favorites, setFavorites] = useState([]);
useEffect(async () => {
const resp = await generalGet({}, '/favorite');
setFavorites(resp.data);
}, [])
return(
<showFoodItems title={"favorite"} items={favorites} history={props.history} />
)
}
export default showAllFavorite;
and my showFoodItem component:
const showFoodItems= ({title , items , history}) => {
return(
<React.Fragment>
<MainMenu title={title} history={history}/>
<div className="container mt-4">
<div className="d-flex flex-wrap">
{
items.map(item => (
<div style={{flex: '50%'}}>
<Link
to={`/recipe/${item.id}`}
key={item.id}
>
<FoodItem
className="foodItem"
name={item.name}
cover={item.cover}
width={'auto'}
/>
</Link>
</div>
))
}
</div>
</div>
</React.Fragment>
)
}
export default showFoodItems;
I want to do this because I want to use the showFoodItems component many times in my app.
I checked the network tab and data is receiving from server. do you have any idea?
The problem is most likely with your component names.
React treats components that start with lower case letters as DOM tags so changing the names to ShowAllFavorite and ShowFoodItems should fix your issue.
You can read more about the reasoning behind this in React's documents here.
I'm doing pokedex (pokemon wiki stuff). I want to change my component view, when clicking on pokemon images (description lookalike). When I click on an image - nothing happens (firstly, I want at least pokemon's name to be added to the pokemonDescription array). What am I doing wrong?
let pokemonDescription = [];
const useForceUpdate = () => {
const [value, setValue] = useState(true);
return () => setValue(value => !value);
}
const forceUpdate = useForceUpdate();
const onPokemonClick = (event) => {
console.log(
"wrapper clicked, event.target - ",
event.target.getAttribute('data-name')
);
pokemonDescription = [];
pokemonDescription.push(event.target.getAttribute('data-name'));
console.log("description array -", pokemonDescription);
forceUpdate();
};
useEffect(() => {
document.querySelector(".wrapper").addEventListener("click", onPokemonClick);
...
return () => {
document.querySelector(".wrapper").removeEventListener("click", onPokemonClick);
};
}, []);
...
return (
<div className="Pokemons">
<div className="column pokemons-list">
<div className="wrapper">
{
pokemonsData.map((p, id) => (
<div className="box" key={ id }>
<img
src={ p.sprites.front_default }
alt="pokemon-img"
title={ p.name }
className="icon"
data-name={p.name}
/>
{ p.name}
<div className="container">
{ pokemonsTypes[id] }
</div>
</div>
))
}
</div>
...
</div>
<div className="column description">
{ pokemonDescription }
</div>
</div>
)
You should add pokemonDescription to your component state
const [pokemonDescription, setPokemonDescription] = useState([]);
Remove the forceUpdate function and hook, it is unnecessary.
Attach the click handlers to the elements with the data-name attribute you are trying to handle.
Map the pokemonDescription state array to renderable JSX. I simply used a div, but you should use whatever your UI design requires.
const onPokemonClick = (event) => {
setPokemonDescription(names => [
...names,
event.target.getAttribute('data-name'),
]);
};
...
return (
<div className="Pokemons">
<div className="column pokemons-list">
<div className="wrapper">
{
pokemonsData.map((p, id) => (
<div className="box" key={ id }>
<img
src={ p.sprites.front_default }
alt="pokemon-img"
title={ p.name }
className="icon"
data-name={p.name}
onClick={onPokemonClick} // <-- attach click handler to img element
/>
{ p.name}
<div className="container">
{ pokemonsTypes[id] }
</div>
</div>
))
}
</div>
...
</div>
<div className="column description">
{pokemonDescription.map(name => (
<div>{name}</div>
))}
</div>
</div>
)
Add pokemonDescription to state instead of some local variable and it will solve your issue.
Try to avoid using forceUpdate, most of the times it means only that you are doing something silly.
I don't what that useForceUpdate does , but here is how would go about adding pokemon names to description array which is a state variable in my answer
const [pokemonDescription , setPokemonDescription ] = useState(null);
const onPokemonClick = (p) => {
const tempPokemonDescription = [...pokemonDescription ];
pokemonDescription.push(p.name);
console.log("description array -", pokemonDescription);
setPokemonDescription(tempPokemonDescription )
};
...
return (
<div className="Pokemons">
<div className="column pokemons-list">
<div className="wrapper">
{
pokemonsData.map((p, id) => (
<div className="box" onClick={e=>onPokemonClick(p)} key={ id }>
<img
src={ p.sprites.front_default }
alt="pokemon-img"
title={ p.name }
className="icon"
/>
{ p.name}
<div className="container">
{ pokemonsTypes[id] }
</div>
</div>
))
}
</div>
...
</div>
<div className="column description">
{ pokemonDescription }
</div>
</div>
)
I am trying to render a child component with images from local folder, but I don't know how to do it.
So I have a const array with details about several projects. Each of the project has its own folder with images. The project name is equal folder name with images
Parent component
import { myProjects } from '../lib/Projects'; //its array with projects
export default class Parent extends Component {
render() {
// function for images
function importAll(r) {
return r.keys().map(r);
}
const projectA = importAll(require.context('../../assets/images/projectA', false, /\.(png|jpe?g|svg)$/));
const projects = myProjects.map((project, i) =>
<Child id={i} key={i} project={project} />)
return (
<div className="main-container">
{projects}
</div>
)
}
}
Child component
export default class Child extends Component {
render() {
const { project } = this.props;
return (
<div className="item">
<div className="desc">
<div className="item-name">
<p>{project.name}</p>
</div>
<div className="item-description">
<p>{project.description}</p>
</div>
<div className="item-tools">
<p>{project.tools}</p>
</div>
</div>
// this part works well
// How to make below part work?
<div className="image-block">
<div className="item-image-first">
<img src={project.name[0]} alt=""/>
</div>
<div className="item-images">
{project.name ? project.name.map((image, index) => {
return (
<div className="image-block-small" key={index}>
<ModalImage
small={image}
large={image}
alt=""
hideDownload={true}
hideZoom={true}
className="modal-image"
/>
</div>
)
})
: null }
</div>
</div>
</div>
)
}
}
Maybe there is a way to add an extra array here?
const projects = myProjects.map((project, i) =>
<Child id={i} key={i} project={project} />)
Any suggestion?
I am following this tutorial
https://nickymeuleman.netlify.com/blog/gatsby-pagination#navigate-to-previousnext-page
Everything is working fine, but I am unable to add const within the class. I am using VSC to code up the site, it just doesn't seem to like it.
This is the class I am trying to place the consts within. As I am new to React I am bit lost on finding a solution without using a plugin.
export default class PostList extends React.Component {
render() {
const posts = this.props.data.allMarkdownRemark.edges
return (
<Layout>
<Head title="Posts" />
<div className={layoutStyles.pageHeader}>
<h2>Posts</h2>
<span>Just my ramberlings</span>
</div>
{posts.map(({ node }) => {
const title = node.frontmatter.title || node.fields.slug
return (
<div className={postPageStyles.postItem}>
<div className={postPageStyles.postItemTitle}>
<h2>{title}</h2>
<span>Posted on {node.frontmatter.date}</span>
</div>
<div>
<p>{node.excerpt}</p>
<Link to={`${node.fields.slug}`}>
<span>Continue Reading</span>
<span role="img"> 👉🏼</span>
</Link>
</div>
</div>
)
})}
</Layout>
)
}
}
You cannot indeed use const in a class "just like that":
class App extends React.Component {
const a = 2 // will throw a syntax error
render(){
return <div>Hello World</div>
}
What you can do is either not use a const to declare the variable as a class field:
class App extends React.Component {
a = "john";
render(){
//now you can access a via `this`
return <div>{`Hello ${this.a}`}</div>
}
Or if you don't need it to be to be somehow "bound" to your component, you can declare it outside of the class.
const a = "john"
class App extends React.Component {
render(){
//you can simply access `a`
return <div>{`Hello ${a}`}</div>
}
I have managed to resolve this. After much googling.
const PostList = props => {
const { currentPage, numPages } = props.pageContext
const isFirst = currentPage === 1
const isLast = currentPage === numPages
const prevPage = currentPage - 1 === 1 ? '/' : (currentPage - 1).toString()
const nextPage = (currentPage + 1).toString()
const posts = props.data.allMarkdownRemark.edges
return (
<Layout>
<Head title="Posts" />
<div className={layoutStyles.pageHeader}>
<h2>Posts</h2>
<span>Just my ramberlings</span>
</div>
{posts.map(({ node }) => {
const title = node.frontmatter.title || node.fields.slug
return (
<div className={postPageStyles.postItem}>
<div className={postPageStyles.postItemTitle}>
<h2>{title}</h2>
<span>Posted on {node.frontmatter.data}</span>
</div>
<div>
<p>{node.excerpt}</p>
<Link to={`${node.fields.slug}`}>
<span>Continue Reading</span>
<span role="img"> 👉🏼</span>
</Link>
</div>
</div>
)
})}
{!isFirst && (
<Link to={prevPage} rel="prev">
← Previous Page
</Link>
)}
{!isLast && (
<Link to={nextPage} rel="next">
Next Page →
</Link>
)}
{Array.from({ length: numPages }, (_, i) => (
<Link
key={`pagination-number${i + 1}`}
to={`posts/${i === 0 ? '' : i + 1}`}
>
{i + 1}
</Link>
))}
</Layout>
)
}
export default PostList
To use the consts I had to change
const PostList = ({ data }) => {
const posts = data.allMarkdownRemark.edges
...
to
const PostList = props => {
const posts = props.data.allMarkdownRemark.edges
which then allowed me to use const { currentPage, numPages } = props.pageContext
Does this work as a functional component? Note that you are no longer accessing this.props.data but can instead just directly access the destructured data variable.
const PostList = ({data}) => {
const posts = data.allMarkdownRemark.edges
return (
<Layout>
<Head title="Posts" />
<div className={layoutStyles.pageHeader}>
<h2>Posts</h2>
<span>Just my ramberlings</span>
</div>
{posts.map(({ node }) => {
const title = node.frontmatter.title || node.fields.slug
return (
<div className={postPageStyles.postItem} key={node.fields.slug}>
<div className={postPageStyles.postItemTitle}>
<h2>{title}</h2>
<span>Posted on {node.frontmatter.date}</span>
</div>
<div>
<p>{node.excerpt}</p>
<Link to={`${node.fields.slug}`}>
<span>Continue Reading</span>
<span role="img"> 👉🏼</span>
</Link>
</div>
</div>
)
})}
</Layout>
)
}
export default PostList
export const query = graphql`{...}`