Redux with Gatsby - wrapped Provider is not recognized - reactjs

I keep encountering the error
could not find react-redux context value; please ensure the component is wrapped in a <Provider>
even though I wrapped my root file in the <Provider> already. My suspicion on what might be wrong is that instead of nested components being wrapped in the <Provider> it is a "Link" to the page that is wrapped instead?
My index.tsx file looks like this
<Provider store={reduxStore}>
<Layout>
<title>Home</title>
<div>
<Image
width="100%"
src="./app-promo1.png"
alt="app promo banner 1"
/>
<Image
width="100%"
src="./app-promo2.png"
alt="app promo banner 2"
/>
</div>
</Layout>
</Provider>
My navbar is inside a Header component which is inside the Layout component.
Layout.tsx
<div>
<LayoutWrapper>
<HeaderWrapper>
<div className="d-none d-md-block">
<Header />
</div>
<div className="d-block d-md-none">
<MobileHeader />
</div>
</HeaderWrapper>
<ContentWrapper>{children}</ContentWrapper>
<FooterWrapper>
<Footer />
</FooterWrapper>
</LayoutWrapper>
</div>
Header.tsx
<Wrapper>
<Container>
<NavWrapper>
<Logo>
<AniLink paintDrip hex="#24B2D8" to="/">
<Image src={logoImg} width="220px" alt="Logo" />
</AniLink>
</Logo>
<div className="d-flex flex-row justify-content-center align-items-center">
<AniLink paintDrip to="/shop" hex="#24B2D8">
<NavItem>Shop</NavItem>
</AniLink>
<AniLink paintDrip to="/activation" hex="#24B2D8">
<NavItem>Activation</NavItem>
</AniLink>
<AniLink cover to="/partners" bg="#24B2D8">
<NavItem>Partners</NavItem>
</AniLink>
<AniLink cover to="/support" bg="#24B2D8">
<NavItem>Support</NavItem>
</AniLink>
</div>
<Button
link="/"
text="Log in"
color="blue"
/>
</NavWrapper>
</Container>
</Wrapper>
The pages that I need the Redux/Provider in are all of these links. ie: /shop, /activation, /partner, and /support. But when I navigate from / to /shop it gives me the error.
One thing to note is that I'm using Gatsby and not create-react-app. I am not sure if there is something special that I would have to do on Gatsby or not.

Your providers need to wrap your component across your application, that's why when you change the page the context is lost. To achieve that in Gatsby, you have available the dual (gatsby-browser.js/gatsby-ssr.js) wrappRootElement API:
const React = require("react")
const { Provider } = require("react-redux")
const createStore = require("./src/state/createStore")
const store = createStore()
exports.wrapRootElement = ({ element }) => {
return (
<Provider store={store}>
{element}
</Provider>
)
}
element stands for the root React element built by Gatsby.

Related

How can I properly bring data from api?

import React from "react";
import noviceImg from "./resources/kull.jpg";
import female1 from "./resources/f1.png";
import female2 from "./resources/f2.png";
import male1 from "./resources/m1.png";
import male2 from "./resources/m2.png";
import kendi from "./resources/kendi.png";
import styles from "./Personel.module.css";
import {
Header,
Subheader,
Content,
kendisi
} from "./components/Personelcomponents";
import { MdBorderColor } from "react-icons/md";
import { pink } from "#material-ui/core/colors";
import Navbar from "../../components/Navbar/Navbar";
import useWindowSize from "../../hooks/useWindowSize";
import Not from "./Not";
import { Container } from "#material-ui/core";
import { connect } from "react-redux";
var DataisLoaded = false;
const mapStateToProps = (state) => ({
kimlikId: state?.account?.principal?.kimlikId,
sonucList: state?.account?.principal?.sonucList,
DataisLoaded: true
});
const Personel = ({ sonucList }) => {
if (!DataisLoaded)
return (
<div>
<h1> Pleses wait some time.... </h1>{" "}
</div>
);
return (
<div className={styles.root}>
<Navbar className={styles.navBar} />
<Not className={styles.not} />
<Content>
<div className={styles.card_k}>
<img alt="" src={kendi} />
<b>
<h4 className={styles.name}>İSİM</h4>
</b>
<p className={styles.cardtext}>
<br />
Baba Adı:
<br />
Yakınlık Derecesi: Kendisi
<br />
<div>
<button_k type="button">Randevu Al</button_k>
</div>
<div></div>
<br />
</p>
</div>
<div className={styles.card_f}>
<img alt="" src={female1} />
<h4 className={styles.name}>İSİM</h4>
<p class="card-text">
Ana Adı:{sonucList.sonucList[0].bireyAd}
<br />
Baba Adı:
<br />
Yakınlık Derecesi:
<br />
<button type="button">Randevu Al</button>
<div></div>
<br />
</p>
</div>
<div className={styles.card_f}>
<img alt="" src={female1} />
<h4 className={styles.name}>İSİM</h4>
<p class="card-text">
Ana Adı:
<br />
Baba Adı:
<br />
Yakınlık Derecesi:
<br />
<button type="button">Randevu Al</button>
<div></div>
<br />
</p>
</div>
<div className={styles.card_m}>
<img alt="" src={male2} />
<h4 className={styles.name}>İSİM</h4>
<p class="card-text">
Ana Adı:
<br />
Baba Adı:
<br />
Yakınlık Derecesi:
<br />
<div>
<button_m type="button">Randevu Al</button_m>
</div>
<div></div>
<br />
</p>
</div>
<div className={styles.characterBox}>
<h2>Sorceress</h2>
<img alt="" src={noviceImg} />
</div>
<div className={styles.characterBox}>
<h2>Sorceress</h2>
<img alt="" src={noviceImg} />
</div>
<div className={styles.characterBox}>
<h2>Sorceress</h2>
<img alt="" src={noviceImg} />
</div>
</Content>
</div>
);
};
export default connect(mapStateToProps)(Personel);
Sorry for the messy code. I'm kinda new to react and js and trying to bring some data from api but I have no idea what I'm doing really. I'm trying to copy other pages in project and they used mapStateProps and somehow I can bring my data (Sonuclist and KimlikId) from there but the problem is it page loaded without data and cause error. (After then it brings data from api and works normally) to prevent that I used if statement and DataisLoaded check but it doesn't return after the first if. Tried using states but apperantly you can do those in class comp only?
I'm trying to copy other pages in project and they used mapStateProps and somehow I can bring my data (Sonuclist and KimlikId) from there but the problem is it page loaded without data and cause error. (After then it brings data from api and works normally) to prevent that I used if statement and DataisLoaded check but it doesn't return after the first if.
First of all, I would suggest using useSelector instead of mapStateToProps.
I have not seen this approach before. mapStateToProps is (was) used in class components. For functional components we have the useSelector hook which does the exact same thing as mapStateToProps (well, without out of the box memoization, but that's out of this context).
It is highly recommended to use the hook, so I suggest you give it a try :)
Now, back to the issue:
I don't see how this can work at any point in time as it looks like you don't use DataisLoaded from your props, it is a completely different variable that has nothing to do with the actual store.
Try deleting var DataisLoaded = false; and do something like:
const Personel = ({ sonucList, DataisLoaded }) => {
Remember that data from your store will only be available this way. Nevertheless I still highly suggest you give useSelector a try.
Hope this helps :)
https://react-redux.js.org/api/hooks#useselector

how to change url without adding another level of path in react router dom 5

i have an api "xyz.com/products/" and i have made an route xyz.com/products/1. This will give me an product with the id 1 . And it will render product page Component with that product details...But now on that particular product page i have an gallery of related product with their own individual "Link" to open in same product page . but when i click on any one of them ....the url changes like this "xyz.com/product/1/23" but i want only to change path like "xyz.com/products/1" --> "xyz.com/products/23"
here is my code snippets
// ///// route and link both are on App Component/////////////////
// this is the route that i have that matches xyz.com/product/1
<Route
path="/product/:id"
render={() => (
<Fragment>
<ProductContext.Provider value={{ productState, productStateDispatch }}>
<Product />
<div className={`overlay ${productState.packageSidebar}`}></div>
</ProductContext.Provider>
</Fragment>
)}
/>;
these are links will go on product page
<Row title="Our best seller">
{homeState.bestSellerProducts.map((product, index) => (
<Link
to={{
pathname: `/product/${product.id}`,
search: `type=${product.type}`,
}}
className="product-link"
key={index}
>
{" "}
<Card {...product} />
</Link>
))}
</Row>
//////////////////////////////
// this is in my product component where i have used one more component called imageGallery inside it. in which we have links////////////
{images.map((imgObj, index) => {
console.log(imgObj);
return (
<div className="item" key={index}>
<Link to={`/${imgObj.id}`} className="product-link">
<div className="img">
<img
height={100}
width={100}
src={imgObj.product_image}
alt="product-img"
/>
</div>
</Link>
</div>
);
})}
// i know i messing in routing i hope will get solution.... i just want that when i click on any link in this imageGallery component .it should be open inside same product page in which i m already present.. thats it
Including exact keyword in the Route component might solve your problem, try out!, demo example:
<Route exact to='/' component={home} />

animation routes with framer motion

Hi i try to animate 2 routes form opacity 1 to 0 on exit. But for some reason on <Link> click the routes will change(ex. '/' => '/chat?name=bob&room=here') but the page content stay the same and it wont render the component of that specific route. Also the animation is working great once i use the "Go back button" from browser.
Anyone have idea why is not working on button click?
App.js
return (
<div>
<Router>
<AnimatePresence exitBeforeEnter>
<Switch location={location} key={location.key}>
<Route path="/" exact component={Login}></Route>
<Route path="/chat" component={ChatRoom}></Route>
</Switch>
</AnimatePresence>
</Router>
</div>
);
Login.js
return (
<motion.div
initial="out"
animate="in"
exit="out"
variants={pageTransition}
className="Login-Container"
>
//same code
<Link
onClick={(event) => (!name || !room ? event.preventDefault() : null)}
to={`/chat?name=${name}&room=${room}`}
>
<button
type="submit"
className="Login-Button"
>
Sign In
</button>
</Link>
</motion.div>
);
ChatRoom.js
return (
<motion.div
initial="out"
animate="in"
exit="out"
variants={pageTransition}
className="ChatRoom-Container"
>
<div className="ChatRoom-NavBar">
<NavLink to="/">
<div
className="ChatRoom-BackButton"
style={{ backgroundImage: `url(${arrow})` }}
></div>
</NavLink>
</div>
</motion.div>
);
};
Your initial and exit prop on motion.div seem to be using the same key i.e "out" try giving the exit prop a different key. Dont forget to adjust your variants as well when you make the change.

How to properly encapsulate inside a React component?

There is a component
return (
<div className={classNames}>
<img
className={[classes["user__avatar"]]}
alt={props.altAvatar}
src={props.srcAvatar}
/>
<h1 className={[classes["user__name"]]}>{props.userName}</h1>
<Button className={[classes["user__logout"]]} onClick={logOut}>
Logout
</Button>
</div>
I initialize it in another component with such data
<UserProfile
className={[classesAppContainer["app__body"]]}
userName={userProfileName}
alt={userProfileName}
src={userProfilePhoto}
/>
The question is, how do I transfer Alt and Src data not from the outside, but encapsulated?

Getting warning about unique "key" when trying to import ReactCSSTransitionGroup into react app

I hope somebody could shed some light into this issue. After many attempts, I was able to import ReactCSSTransitionGroup into my react app correctly. Now I'm getting the following warning and my transition is not working.
Warning: Each child in an array or iterator should have a unique "key" prop.
I wrapped my component in the main App.js file with the ReactCSSTransitionGroup element like this.
return (
<div className="container">
<Navigation />
<div className="app-items-container">
{
this.state.notes.map((note) => {
return(
<ReactCSSTransitionGroup {...transitionOptions}>
<Note noteContent={note.noteContent}
noteId={note.id}
key={note.id}
removeNote={this.removeNote} />
</ReactCSSTransitionGroup>
)
})
}
</div>
<Form addNote={this.addNote} />
</div>
);
My component already has a key passed to it. Where should I apply the key?
I don't think you want the ReactCSSTransitionGroup inside the .map function. It should be outside and ReactCSSTransitionGroup will add it's magic to each of it's children (your Note component).
It works by adding additional lifecycle methods to 'each' of it's children as they are added/removed from the DOM. So there is no need to wrap each of the Note components with ReactCSSTransitionGroup, it should simply have all the Notes as it's children.
The key warning is because ReactCSSTransitionGroup will wrap it's children in a span. When in the .map loop, react will see something like the following:
<span> <Note key={note.id} /> </span>
<span> <Note key={note.id} /> </span>
<span> <Note key={note.id} /> </span>
React will want each of the spans to have a unique key, the child Note key will be ignored.
Moving it outside the map will give you this:
<span>
<Note key={note.id} />
<Note key={note.id} />
<Note key={note.id} />
</span>
And React will be happy as each Note has a key.
Try the following:
return (
<div className="container">
<Navigation />
<div className="app-items-container">
<ReactCSSTransitionGroup {...transitionOptions}>
{this.state.notes.map((note) => {
return(
<Note noteContent={note.noteContent}
noteId={note.id}
key={note.id}
removeNote={this.removeNote} />
)
})
}
</ReactCSSTransitionGroup>
</div>
<Form addNote={this.addNote} />
</div>
);
most likely you should be adding a unique key on <ReactCSSTransitionGroup > as well, could you try the following please?
return (
<div className="container">
<Navigation />
<div className="app-items-container">
{
this.state.notes.map((i, note) => {
return(
<ReactCSSTransitionGroup key={i} {...transitionOptions}>
<Note noteContent={note.noteContent}
noteId={note.id}
key={note.id}
removeNote={this.removeNote} />
</ReactCSSTransitionGroup>
)
})
}
</div>
<Form addNote={this.addNote} />
</div>
);
also, what micposso said makes sense, so it would be nice if you could make sure that node.id is indeed always unique.

Resources