I have this code where I connect all my reducers:
import { combineReducers } from 'redux';
import { connectRouter } from 'connected-react-router';
import { login } from './login';
import { register } from './register';
import { dashboard } from './dashboard';
import { refreshedToken } from './refreshedToken';
import { updateUserReducer } from './updateUser';
import {History} from "history";
const rootReducer = (history: History) =>
combineReducers({
router: connectRouter(history),
dashboard,
login,
refreshedToken,
register,
updateUserReducer,
});
export default rootReducer;
export type RootState = ReturnType < typeof rootReducer >
I my component I do:
const selector = useSelector((s: RootState) => s);
also I get data from selector:
const httpResponse = selector.updateUserReducer.response;
The issue is that I get an error from TypeScript when I hover over updateUserReducer:
TS2339: Property 'updateUserReducer' does not exist on type 'Reducer { router: RouterState ; dashboard: { dashboardRequest: boolean; user: any; error: string; dashboardSuccess: boolean; } | { dashboardRequest: boolean; user: {}; error: any; dashboardSuccess: boolean; }; login: { ...; } | { ...; }; refreshedToken: { ...; } | { ...; }; register: { ...; }; ...'.
Why does this appear and how to solve the issue?
here is redux docs on how to use typescript with redux and react-redux
this code is fine i think the problem is with the return type of your reducer. check the document step by step for finding your exact problem.
Related
i can't get data from Vuex,
in one component this.$store works, but in others components don't work.
Component which work perfectly is SignIn, but in HomeView and List this.$store get me error like : Uncaught (in promise) TypeError: Cannot read properties of undefined (reading '$store')
My store.js:
import { createStore } from "vuex";
const store = createStore({
state: {
logged: false,
token: "",
},
mutations: {
signIn(state) {
state.logged = true;
},
logOut(state) {
state.logged = false;
},
updateToken(state, token) {
state.token = token;
},
},
getters: {
token: (state) => state.token,
}
});
export default store;
main.js:
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap";
import store from "./store/store";
import "./assets/sbx.css";
const app = createApp(App);
app.use(store);
app.use(router);
app.mount("#app");
SignIn function with this.$store
import { defineComponent, ref } from "vue";
import { signIn } from "../../services/Auth/signIn";
const userName = ref('');
const password = ref('');
async function signInUser()
{
const response = await signIn(userName.value, password.value);
if (response.status === 200) {
this.$store.commit("signIn");
this.$store.commit("updateToken", response.data.token);
}
}
export default defineComponent({
setup() {
return {
signInUser,
userName,
password,
};
},
});
And HomeView where this.$store dont work
import { defineComponent } from "vue";
const test = this.$store.getters.token;
export default defineComponent({
setup() {
return {
};
},
});
Hi i am configuring redux store and i need make somethink like this
import { configureStore, getDefaultMiddleware } from '#reduxjs/toolkit'
import createSagaMiddleware from 'redux-saga'
import logger from 'redux-logger'
import { reduxBatch } from '#manaflair/redux-batch';
import rootSaga from '../sagas/root-saga'
import rootReducer from './rootReducer'
const makeStore = (initialState, options) => {
const sagaMiddleware = createSagaMiddleware()
const middleware = [...getDefaultMiddleware(), logger, sagaMiddleware]
const preloadedState = {}
const store = configureStore({
reducer: rootReducer,
middleware,
devTools: process.env.NODE_ENV !== 'production',
preloadedState,
enhancers: [reduxBatch]
})
sagaMiddleware.run(rootSaga)
return store
}
// export type AppDispatch = typeof makeStore.dispatch
export type AppStore = typeof makeStore
export default makeStore
I want to use redux-saga, #reduxjs/toolkit, Next.js, redux
_app.tsx
import React from 'react'
import { Container, AppProps } from 'next/app'
import { Provider } from 'react-redux'
import withRedux from 'next-redux-wrapper'
import withReduxSaga from 'next-redux-saga'
import { ConnectedRouter } from 'connected-next-router'
import GlobalStyles from '../src/globalStyles'
// import { ErrorBoundary } from '../src/components/ErrorBoundary'
import makeStore, { AppStore } from '../src/store'
interface Props extends AppProps {
store: AppStore
}
const MyApp = ({ Component, pageProps, store }: Props) => {
return (
<Container>
<Provider store={store}>
<ConnectedRouter>
<GlobalStyles/>
{/*<ErrorBoundary>*/}
{/*<Layout>*/}
<Component {...pageProps} />
{/*</Layout>*/}
{/*</ErrorBoundary>*/}
</ConnectedRouter>
</Provider>
</Container>
)
}
export default withRedux(makeStore)(withReduxSaga(MyApp))
But i get error in store
No overload matches this call.
Overload 1 of 2, '(props: Readonly<ProviderProps<AnyAction>>): Provider<AnyAction>', gave the following error.
Type '(initialState: any, options: any) => EnhancedStore<{ readonly [$CombinedState]?: undefined; }, AnyAction, (Middleware<{}, any, Dispatch<AnyAction>> | Middleware)[]>' is missing the following properties from type 'Store<any, AnyAction>': dispatch, getState, subscribe, replaceReducer, [Symbol.observable]
Overload 2 of 2, '(props: ProviderProps<AnyAction>, context?: any): Provider<AnyAction>', gave the following error.
Type '(initialState: any, options: any) => EnhancedStore<{ readonly [$CombinedState]?: undefined; }, AnyAction, (Middleware<{}, any, Dispatch<AnyAction>> | Middleware)[]>' is not assignable to type 'Store<any, AnyAction>'.
I tried example from here but there don't use Next.js withRedux so i need combine these two ways.
I don't know how should it looks like. Can someone help me please? :)
UPDATE!
I resolve my problem with configuration store.ts
import { configureStore, getDefaultMiddleware } from '#reduxjs/toolkit'
import createSagaMiddleware from 'redux-saga'
import logger from 'redux-logger'
import { reduxBatch } from '#manaflair/redux-batch';
import rootSaga from '../sagas/root-saga'
import rootReducer from './rootReducer'
const sagaMiddleware = createSagaMiddleware()
const middleware = [...getDefaultMiddleware(), logger, sagaMiddleware]
const preloadedState = {}
const store = configureStore({
reducer: rootReducer,
middleware,
devTools: process.env.NODE_ENV !== 'production',
preloadedState,
enhancers: [reduxBatch]
})
// #ts-ignore TODO: resolve
store.sagaTask = sagaMiddleware.run(rootSaga)
export type AppDispatch = typeof store.dispatch
export type AppStore = typeof store
export default store
and changed _app.tsx
const makeStore = () => store
export default withRedux(makeStore)(withReduxSaga(MyApp))
I am using mobx react a type script
Why does <MainNote/> show the error
Do i just need to set default props?
Property 'profileStore' is missing in type '{}' but required in type 'Readonly<AppProps>'.ts(2741)
MainNote.tsx(9, 3): 'profileStore' is declared here.
(alias) class MainNote
import MainNote
I do not want to pass the prop in as it is a prop ejected by mobx.
Thanks for the help
The code is below
import React, { Component } from 'react';
import MainNote from './MainNote';
import { observable, computed } from 'mobx'
import { observer, inject, IStoresToProps } from 'mobx-react'
import { IStore } from '../interfaces/store/IStore'
import style from '../styles/App.module.css';
import { IProfileStore } from '../interfaces/Profile/IProfileStore';
import { iProfile } from '../interfaces/Profile/iProfile';
interface AppProps {
profileStore?: IProfileStore
}
export interface IProfileStore {
profile: iProfile,
counter: number,
loadProfile?: () => void
}
#inject("profileStore")
#observer
class App extends Component<AppProps> {
static defaultProps = { profileStore: {counter: 0}};
render() {
return (
<div className={`container-fluid w-100 h-100 ${style.background}`}>
<MainNote/>
{console.log('props', this.props.profileStore) }
</div>
);
}
}
export default App;
import React, { Component } from 'react';
import { observable, computed } from 'mobx'
import { observer, inject, IStoresToProps } from 'mobx-react'
import style from '../styles/MainNote.module.css'
import { IStore } from '../interfaces/store/IStore'
import {IProsStore} from '../interfaces/store/IPropsStore'
interface AppProps {
profileStore: IProfileStore;
}
interface IProfileStore {
profile: iProfile;
counter: number;
loadProfile?: () => void;
}
interface iProfile
{
Details: iDetails;
Address: iAddress;
Notes: iNote[];
}
interface iDetails
{
Name: string;
Email: string;
Age: number;
CellNumber: number;
}
interface iAddress
{
No: number;
Road: string;
Street: string;
Place: string;
}
interface iNote
{
Date: Date | string;
Subject: string;
Text: string;
Private: boolean;
Archived: boolean;
}
#inject("profileStore")
#observer
class MainNote extends Component<AppProps> {
render() {
const { Address } = this.props.profileStore.profile;
console.log('s', this.props.profileStore.profile.Address.No)
return (
<div className={style.makeLookCool}>
<ul className="list-group">
<li className="list-group-item">{Address.No} {Address.Place} {Address.Road} {Address.Street}</li>
</ul>
</div>
);
}
}
export default MainNote;
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import './styles/index.css';
import App from "./componenets/App";
import { Provider } from 'mobx-react';
import {IProsStore} from './interfaces/store/IPropsStore'
import * as serviceWorker from './serviceWorker';
// import NotesStore from "./NotesStore";
// import CounterStore from "./CounterStore";
import ProfileStore from './store/ProfileStore';
import { IStore } from './interfaces/store/IStore';
const Store: IStore = {
profileStore: new ProfileStore(),
};
ReactDOM.render(
<Provider {...Store}>
<App />
</Provider>,
document.getElementById('root'));
Make profileStore props mandatory from:
interface AppProps {
profileStore: IProfileStore;
}
to optional
interface AppProps {
profileStore?: IProfileStore;
}
The answer is to set the default prop in the component
static defaultProps = {profileStore:{}}
For others who see the same error.
The same problem happens when you use withStyles and you import that class in a curly braces like the following:
import { MainNote } from './MainNote';
this imports directly the class itself without applying the styles and therefore it lacks the classes. You just need to remove the curly braces to import the default export:
import MainNote from './MainNote';
I am trying to figure out how to pass down props into components when using typescript.
The error I receive if I try to pass down any prop anywhere, whether it be local state or anything but {...this.props}. But if I pass down this.props, I don't get anything that I want on the other end. Instead I get history, location, match with their applicable defaults and staticContext: undefined. If I try to pass down actions, as in my example below, then it will be undefined.
The error I get as a result is
client:157 [at-loader] ./src/containers/App/index.tsx:25:31
TS2339: Property 'actions' does not exist on type 'IntrinsicAttributes & IntrinsicClassAttributes<Home> & Readonly<{ children?: ReactNode; }> & Read...'.
My App.tsx is below:
import * as React from 'react';
import * as HomeActions from '../../actions/home';
import * as style from './style.css';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { RouteComponentProps } from 'react-router';
import { RootState } from '../../reducers';
import Home from '../../components/Home';
export namespace App {
export interface Props extends RouteComponentProps<void> {
actions: typeof HomeActions
}
export interface State {
/* empty */
}
}
export class App extends React.Component<App.Props, App.State> {
render() {
return (
<div>
<Home {...this.props} actions={this.props.actions}/>
{this.props.children}
</div>
);
}
}
function mapStateToProps(state: RootState) {
return {
home: state.home
};
}
function mapDispatchToProps(dispatch) {
return {
actions: bindActionCreators(HomeActions as any, dispatch)
};
}
connect(mapStateToProps, mapDispatchToProps);
In the home component, when I log this.props.actions in onComponentDidMount(){} then I get undefined.
You should pass your component to connect and export connected component instead of just component.
export connect(mapStateToProps, mapDispatchToProps)(App);
I can not understand how to deal with new typings of Redux.
Right now i am trying to complete this tutorial https://maxfarseer.gitbooks.io/redux-course-ru/content/index.html
At this moment I am on "Creating Store" phase with this simple code below:
store/configureStore.ts
import {createStore, Reducer} from 'redux';
import rootReducer from '../reducers';
export default function configureStore(initialState) {
const store = createStore(rootReducer, initialState);
if (module.hot) {
module.hot.accept('../reducers', () => {
const nextRootReducer=require('../reducers');
store.replaceReducer(nextRootReducer);
})
}
return store;
}
When I try to compile it messages me about this error:
ERROR in ./src/store/configureStore.ts
(10,34): error TS2345: Argument of type '{}' is not assignable to parameter of type '<A extends Action>(state: any, action: A) => any'.
Type '{}' provides no match for the signature '<A extends Action>(state: any, action: A): any'
This is my index file of reducers
import {combineReducers} from "redux/index";
import page from './page';
import user from './user';
const rootReducer = combineReducers({
page,
user
});
export default rootReducer;
//page.ts
const initialState = {
year: 2016,
photos: []
};
function page(state = initialState,
action = {type: '', payload: null}) {
return state
}
export default page;
//user.ts
const initialState = {
name: 'Аноним'
};
export default function user(state = initialState,
action = {type: '', payload: null}) {
return state
}