I am getting this error /!\ You are using legacy implementaion. Please update your code: use createWrapper() and wrapper.useWrappedStore(). when I compile my application. The application works fine, but I do not know why I get the error. I tried configuring similar to other projects on google and nothing seems to work.
I tried using this solution, but had no luck. Not sure how to fix this.
Here is my _app.tsx
import type { AppProps } from 'next/app'
import { Toaster } from 'react-hot-toast';
import { useRouter } from 'next/router';
import { wrapper } from '../features/store';
import useAuth from '../hooks/useAuth';
import useDarkMode from '../hooks/useDarkMode';
import '../styles/global.css';
const App = ({ Component, pageProps }: AppProps) => {
useAuth();
useDarkMode();
const router = useRouter();
return (
<main>
<Component {...pageProps} key={router.asPath} />
<Toaster
position="bottom-center"
toastOptions={{
duration: 3000,
}}
/>
</main>
)
};
export default wrapper.withRedux(App);
here is index.tsx
import { useEffect } from "react";
import { useRouter } from "next/router";
import { useSelector } from "react-redux";
import { User } from "../domain/accounts/user";
import Loading from "../icons/Loading";
import useUser from "../hooks/useUser";
const Home = () => {
const user = useUser();
const router = useRouter();
useEffect(() => {
if (user.isAuthenticated !== null) {
if (user.isAuthenticated) router.push('/home');
if (!user.isAuthenticated) router.push('/explore')
}
}, [user.isAuthenticated]);
return (
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
minHeight: '95vh',
}}>
<Loading height={80} width={80} />
</div>
);
}
export default Home;
here is store.js
import { configureStore } from "#reduxjs/toolkit";
import { userSlice } from "./user";
import { userPreferenceSlice } from "./userPreference";
import { createWrapper } from "next-redux-wrapper";
const makeStore = () => {
return configureStore({
reducer: {
user: userSlice.reducer,
userPreference: userPreferenceSlice.reducer,
},
});
}
export const wrapper = createWrapper(makeStore);
Did you try npm install next-redux-wrapper
Then, in _app.tsx try replaceing the wrapper.withRedux import with import { useWrappedStore } from "next-redux-wrapper";
And instead of using the wrapper.withRedux function, try using the useWrappedStore method:
const MyAppWithRedux = useWrappedStore(MyApp);
export default MyAppWithRedux;
Related
Edit:
I was not using
import Link from 'next/link';
in my Header.tsx component.
Now it works.
Don't know what I am doing wrong right here.
I try to make global state (to indicate if user is logged in or not) that just flows through the pages and I try to do it with react's hook useContext.
It is not working like how I would like to make it work. When I toggleLogged and go to another page, the context has default value and not the changed one.
I think the problem I am facing is something really small or a fundemantal thing that I just can't see.
Here is how my UserContext.ts file looks:
import { createContext, useContext } from 'react';
type userContextType = {
isLogged: boolean;
toggleLogged: () => void;
};
const userContextDefault: userContextType = {
isLogged: false,
toggleLogged: () => {},
};
export const UserContext = createContext(userContextDefault);
export function useUserContext() {
return useContext(UserContext);
}
Here is my Layout.tsx:
import React, { useState } from 'react';
import Header from './Header';
const Layout = (props: any) => {
const { children } = props;
return (
<div className='container'>
<Header />
{children}
</div>
);
};
export default Layout;
And lastly here is my _app.tsx:
import type { AppContext, AppProps } from 'next/app';
import Layout from '../components/Layout';
import { useState } from 'react';
import { UserContext } from '../components/UserContext';
import '../styles/globals.css';
const MyApp = ({ Component, pageProps }: AppProps) => {
const [isLogged, setIsLogged] = useState(true);
const toggleLogged = () => {
setIsLogged((isLogged) => !isLogged);
};
return (
<UserContext.Provider value={{ isLogged, toggleLogged }}>
<Layout>
<Component {...pageProps} />;
</Layout>
</UserContext.Provider>
);
};
export default MyApp;
Thanks for any help in advance.
You need to return the provider in the context, and then reference the instance in _app.js.
Here's my AuthContext (as an example). Don't worry about the specific code, but use my implementation as the foundation, and you'll be up and running in no time!
import { createContext, useContext, useEffect, useState } from 'react'
import { auth } from '../firebase'
const AuthContext = createContext()
export function useAuth() {
return useContext(AuthContext)
}
export function AuthProvider({ children }) {
const [currentUser, setCurrentUser] = useState()
const [loading, setLoading] = useState(true)
function login(email, password) {
return auth.signInWithEmailAndPassword(email, password)
}
function signOut() {
return auth.signOut();
}
function signUp(email, password) {
return auth.createUserWithEmailAndPassword(email, password)
}
function getUser() {
return auth.currentUser
}
function isAdmin() {
return auth.currentUser.getIdTokenResult()
.then((idTokenResult) => {
if (!!idTokenResult.claims.admin) {
return true
} else {
return false
}
})
}
function isEditor() {
}
useEffect(() => {
const unsubscribe = auth.onAuthStateChanged(user => {
setCurrentUser(user)
setLoading(false)
})
return unsubscribe
}, [])
const value = {
currentUser,
getUser,
login,
signOut,
signUp
}
return (
<AuthContext.Provider value={value}>
{ !loading && children }
</AuthContext.Provider>
)
}
My _app.js file:
import '../styles/globals.scss'
import { motion, AnimatePresence } from 'framer-motion'
import { useRouter } from 'next/router'
import Header from '../components/Header'
import Footer from '../components/Footer'
import { AuthProvider } from '../contexts/AuthContext'
import { CartProvider } from '../contexts/CartContext'
import { ThemeProvider } from '#material-ui/core'
import theme from '../styles/theme'
export default function App({ Component, pageProps }) {
const router = useRouter()
return(
<AnimatePresence exitBeforeEnter>
<CartProvider>
<AuthProvider>
<ThemeProvider theme={theme}>
<Header />
<motion.div key={router.pathname} className="main">
<Component { ...pageProps } />
<Footer />
</motion.div>
</ThemeProvider>
</AuthProvider>
</CartProvider>
</AnimatePresence>
)
}
I'm new to programming and following this video, my code until now has had no problems, but when I try
console.log(currentUser);
It returns undefined while it shouldn't, the user is logged in and all of their information is correct in Firebase. Also, my code doesn't show any errors.
This is the code:
import React, { Component } from 'react';
import {Text, View} from 'react-native';
import firebase from 'firebase'
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchUser } from '../../redux/actions/index';
export class Main extends Component {
componentDidMount() {
this.props.fetchUser();
}
render() {
const { currentUser } = this.props;
console.log(currentUser)
if (currentUser==undefined){
return(
<View></View>)
}
return (
<View style={{ flex: 1, justifyContent: 'center'}}>
<Text>User is logged in</Text>
</View>
)
}
}
const mapStateToProps = (store) => ({
currentUser: store.userState.currentUser
})
const mapDispatchProps = (dispatch) => bindActionCreators({fetchUser}, dispatch)
export default connect(null, mapDispatchProps)(Main);
And this is the parent component code:
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
require('dotenv').config();
import firebase from 'firebase';
const firebaseConfig = {
//personal info
};
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import rootReducer from './redux/reducers';
import thunk from 'redux-thunk';
const store = createStore(rootReducer, applyMiddleware(thunk))
if(firebase.apps.length === 0){
firebase.initializeApp(firebaseConfig)
}
import {NavigationContainer} from '#react-navigation/native';
import {createStackNavigator} from '#react-navigation/stack';
import {createMaterialTopTabNavigator} from 'react-navigation-tabs';
import LandingScreen from './Components/auth/Landing';
import RegisterScreen from './Components/auth/Register';
import MainScreen from './Components/auth/Main';
const Stack = createStackNavigator();
export class App extends Component {
constructor(props) {
super(props);
this.state = {
loaded: false,
}
}
componentDidMount(){
firebase.auth().onAuthStateChanged((user) => {
if (!user){
this.setState({
loggedIn: false,
loaded: true,
})
}else{
this.setState({
loggedIn: true,
loaded: true,
})
}
})
}
render() {
const { loggedIn, loaded } = this.state
if (!loaded){
return(
<View style={{ flex: 1, justifyContent: 'center'}}>
<Text>Loading</Text>
</View>
)
}
if (!loggedIn) {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Landing">
<Stack.Screen name="Landing" component={LandingScreen} options={{headerShown: false}}/>
<Stack.Screen name="Register" component={RegisterScreen}/>
</Stack.Navigator>
</NavigationContainer>
);
}
return(
<Provider store={store}>
<MainScreen/>
</Provider>
)
}
};
export default App
I'm tranfer reactjs project to nextjs with react-redux, redux, nexti18next, next-redux-wrapper here is _app.js and redux.js it run right but if i add withRedux it is error. Please tell me how to resolve this problem or advide me some solution!
import React from "react";
import App, { Container } from "next/app";
import { appWithTranslation } from "../i18n";
import ScrollToTop from "../components/ScrollToTop";
import { createBrowserHistory } from "history";
import { Provider } from "react-redux";
import storeConfig from "../redux";
import compose from "recompose/compose";
const history = createBrowserHistory();
const store = storeConfig();
import withRedux from "next-redux-wrapper";
class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
return { pageProps };
}
render() {
const { Component, pageProps } = this.props;
console.log(store)
return (
<Container>
<ScrollToTop>
<Provider store={store}>
<Component {...pageProps} />
</Provider>
</ScrollToTop>
</Container>
);
}
}
export default compose(appWithTranslation)(MyApp);
import { createStore, combineReducers, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import getQuote, { initGetQuoteState } from './Modules/GetQuote';
import getSlider, { initGetSliderState } from './Modules/GetSlider';
import getUser, {initGetUserState } from './Modules/User';
import {composeWithDevTools } from 'redux-devtools-extension'
const initState = {
getQuote: initGetQuoteState,
getSlider: initGetSliderState,
getUser: initGetUserState
};
const rooteReducer = combineReducers({
getQuote,
getSlider,
getUser
});
const store = () => createStore(rooteReducer, initState, composeWithDevTools(applyMiddleware(thunk)))
export default store;
Here is example of NextJS/Typescript/Redux/Styled-Components/next-i18next app sample.
// _app.tsx
import * as React from "react";
import App, { AppInitialProps, AppContext } from "next/app";
import withRedux from "next-redux-wrapper";
import { Provider } from "react-redux";
import { ThemeProvider } from "styled-components";
import { theme } from "#Definitions/Styled";
import { appWithTranslation } from "#Server/i18n";
import { AppWithStore } from "#Interfaces";
import { makeStore } from "#Redux";
import "#Static/css/main.scss";
class ProgressiveWebApp extends App<AppWithStore> {
static async getInitialProps({
Component,
ctx,
}: AppContext): Promise<AppInitialProps> {
const pageProps = Component.getInitialProps
? await Component.getInitialProps(ctx)
: {};
return { pageProps };
}
render() {
const { Component, pageProps, store } = this.props;
return (
<Provider store={store}>
<ThemeProvider theme={theme}>
<Component {...pageProps} />
</ThemeProvider>
</Provider>
);
}
}
export default withRedux(makeStore)(appWithTranslation(ProgressiveWebApp));
//i18.ts
import NextI18Next from "next-i18next";
const NextI18NextInstance = new NextI18Next({
defaultLanguage: "en",
otherLanguages: ["es"],
});
export const {
appWithTranslation,
withTranslation,
useTranslation,
i18n,
} = NextI18NextInstance;
export default NextI18NextInstance;
and I have path alias in tsconfig
"paths": {
"#Definitions/*": ["definitions/*"],
"#Interfaces": ["interfaces"],
"#Redux": ["redux-store"],
"#Server/*": ["server/*"]
}
hope this helps somebody!
I have a connected component and have integrated MaterialUI in my component. For some reason, the tests keep on failing and I am not able to find some article online to resolve this.
Please advice.
Below is my code.
import React, {Component} from 'react';
import {connect} from 'react-redux';
import SourceCurrencyInput from './components/SourceCurrencyInput';
import TargetCurrencyInput from './components/TargetCurrencyInput';
import {fetchCurrencyConverterRates} from './actions/currencyConverterActions';
import CurrencyConverterValue from './components/CurrencyConverterValue';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import {withStyles} from '#material-ui/core/styles';
import './App.css';
import {
changeSourceCurrencyValue,
changeTargetCurrencyValue
} from './actions/actions';
const styles = {
root: {
flexGrow: 1,
},
grow: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
class App extends Component {
componentDidMount() {
this.props.fetchCurrencyConverterRates(
this.props.srcCurrencyType,
this.props.tgtCurrencyType
);
}
componentDidUpdate(prevProps, prevState, snapshot) {
if (prevProps.srcCurrencyType !== this.props.srcCurrencyType
|| prevProps.tgtCurrencyType !== this.props.tgtCurrencyType) {
this.props.fetchCurrencyConverterRates(
this.props.srcCurrencyType,
this.props.tgtCurrencyType);
}
}
clearAll = () => {
this.props.sourceValue('');
this.props.targetValue('');
};
render() {
const {srcCurrencyType, tgtCurrencyType, srcCurrencyValue, tgtCurrencyValue, currencyConversionRate, classes} = this.props;
return (
<div className="App">
<AppBar position="static">
<Toolbar>
<Typography variant="h6" color="inherit" className={classes.grow}>
Currency Converter by Arun Manohar
</Typography>
</Toolbar>
</AppBar>
<header className="App-header">
<SourceCurrencyInput/>
<TargetCurrencyInput/>
<Button variant="contained" color="primary" className={classes.button}
onClick={() => this.clearAll()}>Clear</Button>
</header>
<CurrencyConverterValue srcCurrencyType={srcCurrencyType}
tgtCurrencyType={tgtCurrencyType}
srcCurrencyValue={srcCurrencyValue}
tgtCurrencyValue={tgtCurrencyValue}
currencyConversionRate={currencyConversionRate}
/>
<footer><a href={'https://currencyconverterapi.com'} target={'_blank'}>API from currencyconverterapi.com</a></footer>
</div>
);
}
}
const mapStateToProps = state => {
return {
srcCurrencyType: state.currencyConverterReducer.sourceCurrencyType,
tgtCurrencyType: state.currencyConverterReducer.targetCurrencyType,
srcCurrencyValue: state.currencyConverterReducer.sourceCurrencyValue,
tgtCurrencyValue: state.currencyConverterReducer.targetCurrencyValue,
currencyConversionRate: state.getConvertedRates.data[0]
};
};
const mapDispatchToProps = (dispatch) => ({
fetchCurrencyConverterRates: (src, tgt) => dispatch(fetchCurrencyConverterRates(src, tgt)),
sourceValue: (val) => dispatch(changeSourceCurrencyValue(val)),
targetValue: (val) => dispatch(changeTargetCurrencyValue(val)),
});
export default connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(App));
Below is my test case.
import React from 'react';
import {Provider} from 'react-redux';
import configureStore from 'redux-mock-store';
import App from './App';
import {createMount} from '#material-ui/core/test-utils';
const mockStore = configureStore();
const initialState = {sourceCurrencyType: 'USD'};
const store = mockStore(initialState);
describe('<App />', () => {
let mount;
beforeEach(() => {
mount = createMount();
});
it('should work', () => {
const wrapper = mount(<Provider store={store}><App/></Provider>);
console.log(wrapper.debug());
});
});
This is the error I get.
TypeError: Cannot read property 'sourceCurrencyType' of undefined
I just need a way to access this component in my tests. Please help me out.
Your initial state must keep the same structure with the reducer object, such:
const initialState = {
currencyConverterReducer: {
sourceCurrencyType: 'USD',
// rest of attributes of currencyConverterReducer
}
};
Being a newbie to react native ,I am finding it difficult to connect my redux with react native and make it work. After javascript bundle finishes ,I see an error "can't read property type of undefined" or "could not find store in either the context or props of "connect".Either wrap the root component in a or explicitly pass "store" as prop.I don't see any of the console.log working except for reducer .
Here is the action that I am using
import {ADD_PLACE,DELETE_PLACE,DESELECT_PLACE,SELECT_PLACE} from './actiontypes';
export const addPLace =(placeName) =>{
console.log('addPLace is being dispatched now');
console.log('In addPLace reducer');
return{
type:ADD_PLACE,
payload:{
placeName:placeName
}
};
};
export const deletePlace =()=>{
return{
type:DELETE_PLACE
};
}
export const selectedPlace =(key) =>{
return{
type:SELECT_PLACE,
payload:{
placekey:key
}
};
};
export const deselectPlace =()=>{
return {
type:DESELECT_PLACE
};
};
Here is the reducer part
import {ADD_PLACE,DELETE_PLACE,SELECT_PLACE,DESELECT_PLACE} from '../actions/actiontypes';
import PlaceImage from "../../../src/assets/download.jpeg";
const INITIAL_STATE={
places:[],
selectedPlace:null
}
const reducer =(action,state=INITIAL_STATE) =>{
console.log('INside reducer');
console.log(action);
switch(action.type){
case ADD_PLACE:
return {
...state,
places:state.places.concat({
key:Math.random(),
name:action.payload.placeName,
image:placeImage
})
};
case DELETE_PLACE:
return{
...state,
places:state.places.filter(place =>{
return place.key !== state.selectedPlace.key;
}),
selectPlace:null
};
case SELECT_PLACE:
return{
...state,
selectedPlace:state.places.find(place=>{
return place.key ===action.payload.placekey;
})
};
case DESELECT_PLACE:
return{
...state,
selectPlace:null
};
default:
return state;
}
}
export default reducer;
Here is the App.js
import React, { Component } from "react";
//import { StyleSheet, Text, View, TextInput, Button } from "react-native";
import store from './src/store/reducers/index.js';
import {Provider} from 'react-redux';
//import {createStore} from 'redux';
//import {connect} from 'react-redux';
import Home from './Home.js';
export default class App extends React.Component {
render() {
console.log('inside App');
console.log(store);
return (
<Provider store={store}>
<Home />
</Provider>
);
}
}
Here is the Home.js
import React, { Component } from "react";
import { StyleSheet, Text, View, TextInput, Button } from "react-native";
//import ListItem from './src/components/ListItem';
import PlaceInput from "./src/components/PlaceInput";
import PlaceList from "./src/components/PlaceList";
//import PlaceImage from "./src/assets/download.jpeg";
import PlaceDetail from "./src/components/PlaceDetail";
//import configureStore from './src/store/reducers/index.js';
//import {Provider} from 'react-redux';
//import {createStore} from 'redux';
import {connect} from 'react-redux';
import {addPLace,deletePlace,selectedPlace,deselectPlace} from './src/store/actions';
//const store=configureStore();
class Home extends React.Component {
placeAddedHandler =val=>{
console.log('Val is ',val);
console.log(val);
this.props.onAddPlace(val);
};
placeSelectHandler =id=>{
console.log('id is');
this.props.onSelectPlace(id);
};
placeDeleteHandler =() =>{
console.log('inside delete handler');
this.props.onDeletePlace();
};
modelClosedHandler =() =>{
console.log('iinside close handler');
this.props.onDeslectPlace();
}
render() {
console.log('Inside render function');
return (
<View style={styles.container}>
<PlaceInput onPlaceAdded={this.placeAddedHandler}/>
<PlaceList places={this.props.places} onItemSelected={this.placeSelectHandler}/>
<PlaceDetail
selectedPlace={this.props.selectedPlace}
onItemDeleted={this.placeDeleteHandler}
onModalClosed={this.modelClosedHandler}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding:30,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'flex-start',
},
});
const mapStateToProps=state => {
console.log('Inside mapStateToProps ');
console.log(state );
return {
places:state.places.places,
selectedPlace:state.places.selectPlace
};
}
const mapDispatchToProps = dispatch =>{
return {
onAddPlace:(name)=>dispatch(addPLace(name)),
onDeletePlace:()=>dispatch(deletePlace()),
onSelectPlace:(id)=>dispatch(selectedPlace(id)),
onDeslectPlace:()=>dispatch(deselectPlace())
};
}
export default connect(mapStateToProps,mapDispatchToProps)(Home);
Link to github repo of project at this moment
github link
Looks like you have made a small import/export error.
In your reducers/index.js you are exporting it as a non default value which you are trying to import as default value in App.js.
import store from './src/store/reducers/index.js';
should be
import {store} from './src/store/reducers/index.js';
Let me know if it works.