Exporting a function declared as constant in ES6 - react-native

I followed a guide to implement REDUX in my react-native app. I am trying to implement actions but my eslintkeeps on giving this error on 8th line-
[eslint] Prefer default export. (import/prefer-default-export)
My code is -
import * as types from './types';
const incrementCounter = counterValue => ({
type: types.INCREMENT_COUNTER,
counterValue,
});
export { incrementCounter };
My question is what is the proper way to export this constant function in ES6 ?

The simplest change would be to add as default to your export { incrementCounter };. However, to export your function as the default export you'd rather write
import * as types from './types';
export default counterValue => ({
type: types.INCREMENT_COUNTER,
counterValue,
});
or
import * as types from './types';
export default function incrementCounter(counterValue) {
return {
type: types.INCREMENT_COUNTER,
counterValue,
};
}

In config.js
// Declaration of const
const config = {
name: 'test'
};
export default config
In another file
// Using const
import * as config from '../config';
let name = config.name;

import/prefer-default-export is a questionable rule,
using default exports you will lose type consistence and your IDE won't be longer able to help you with refactoring, inspection and code completion.
you will be always able to import with a different name using import aliases: import {incrementCounter as foo} from 'incrementCounter'
It may appear as a personal opinion, but, I strongly suggest you to keep named exports and edit your .eslintrc:
{
"rules": {
"import/prefer-default-export" : 0
}
}
Please, refer to this discussion:
https://github.com/airbnb/javascript/issues/1365

Related

Expected root reducer function. Instead received: undefined error in react native application

I am building a react native app but I get following error Error: Expected the root reducer to be a function. Instead, received: 'undefined'
I have a index.js file which exports the Reducers.
import { combineReducers } from "redux";
const Reducers = combineReducers();
export default Reducers;
In the App.js file I create a store const store = createStore(rootReducers, composeWithDevTools(applyMiddleware(thunk)));
But when I run expo start I get the above error. I am exporting a reducer function right ?
You are not passing any reducer to your combineReducers().
Please add two or more reducer to combineReducers function.
Like
const rootReducer = combineReducers({
appReducer: appReducer,
authReducer: authReducer,
});
Yes, you are exporting a reducer function. However, you are not using the combineReducers function correctly:
The combineReducers helper function turns an object whose values are different reducing functions into a single reducing function you can pass to createStore.
The combineReducers function expects a single argument:
An object whose values correspond to different reducing functions that
need to be combined into one.
You are calling combineReducers without any arguments, so the first argument becomes undefined, which is why you are getting Error: Expected the root reducer to be a function. Instead, received: 'undefined'.
Here is a toy example of how it can be used:
export default function firstReducer(state = {}, action) {
switch (action.type) {
// do something based on the action.type
default:
// default case just returns the state
return state;
}
}
export default function secondReducer(state = {}, action) {
switch (action.type) {
// do something based on the action.type
default:
// default case just returns the state
return state;
}
}
rootReducer = combineReducers({first: firstReducer, second: secondReducer})
// This would produce the following state object
{
first: {
// state managed by firstReducer
},
second: {
// state managed by secondReducer
}
}
I faced the same issue. In my case, the problem was the wrong import of reducer.
If you wrote the rootReducer in reducers.js as the following
export function rootReducer() {
...
}
Please use it when you create a store like this.
import { rootReducer } from './reducers';
const store = createStore(rootReducers);
But if you created the rootReducer like this
export default function rootReducer() {
...
}
You should import it without braces.
import rootReducer from './reducers';
const store = createStore(rootReducers);

Separating store into separate files (actions, mutations, getters) get api calls now not working

I'm trying to spilt up my store firstly so all the getters, actions and mutations are in separate files as per this answer: https://stackoverflow.com/a/50306081/5434053
I have API calls in a services file, the POST api calls seem to work but the GET ones do not, the action seems to get nothing back. Have I missed something?
import Vue from 'vue';
import Vuex from 'vuex';
import actions from './actions';
import getters from './getters';
import mutations from './mutations';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
status: '',
token: localStorage.getItem('token') || '',
user: {},
movie: {},
movies: {}
},
actions,
getters,
mutations,
});
store/actions.js
import axios from 'axios'
import {APIService} from '../services/APIService';
const apiService = new APIService();
let getMovies = async ({commit, state, getter}) => {
try {
await apiService.getMovies(localStorage.getItem('token')).then((data, error) => {
for (const movie of data.data.data.movies) {
movie.edit = false;
movie.deleted = false;
}
this.movies = data.data.data.movies;
console.log(data)
commit("fetch_movies", this.movies);
})
} catch(error) {
commit('auth_error')
localStorage.removeItem('token')
console.log(error)
}
}
export default {
getMovies,
};
It looks like you are importing actions from ./actions. However, when I look at your file at store/actions.js you are not exporting anything.
For JavaScript modules to work you have to add export statements to your files - so you can import the exported variables/properties somewhere else.
Also: You seem to only declare the function getMovies() without adding it to an actions object (which you import in store.js).
Try this:
// in store/actions.js
// your code..
const actions = {
getMovies,
}
export default actions;
Edit:
Just noticed you also use this in your action. If I am not mistaken it should be undefined as you only work with lambdas (Arrow Functions).

Nuxtjs using Vuex-module-decorator doesn't wordk

I want to use my vuex modules as classes to make my code more clean and readable. I used the section (Accessing modules with NuxtJS) at the bottom of this document: https://github.com/championswimmer/vuex-module-decorators/blob/master/README.md
I've searched for the solution for almost 3 days and tried out this link:
vuex not loading module decorated with vuex-module-decorators
but, it didn't work.
Also, I used getModule directly in the component like the solution in this issue page: https://github.com/championswimmer/vuex-module-decorators/issues/80
import CounterModule from '../store/modules/test_module';
import { getModule } from 'vuex-module-decorators';
let counterModule: CounterModule;
Then
created() {
counterModule = getModule(CounterModule, this.$store);
}
Then, accessing method elsewhere
computed: {
counter() {
return counterModule.getCount
}
}
it didn't work for me!
This is my Module in store folder in Nuxtjs project:
import { ICurrentUser } from '~/models/ICurrentUser'
import { Module, VuexModule, Mutation, MutationAction } from 'vuex-module-decorators'
#Module({ stateFactory: true, namespaced: true, name: 'CurrentUserStore' })
export default class CurrentUser extends VuexModule {
user: ICurrentUser = {
DisplayName: null,
UserId: null,
};
#Mutation
setUser(userInfo: ICurrentUser) {
this.user = userInfo;
}
get userInfo() {
return this.user;
}
}
In index.ts file in sore folder:
import { Store } from 'vuex'
import { getModule } from 'vuex-module-decorators'
import CurrentUser from './currentUser'
let currentUserStore: CurrentUser
const initializer = (store: Store<any>): void => {
debugger
currentUserStore = getModule(CurrentUser, store)
}
export const plugins = [initializer]
export {
currentUserStore,
}
I think the problem stems from this line:
currentUserStore = getModule(CurrentUser, store)
currentUserStore is created as object but properties and methods are not recognizable.
when I want to use getters or mutation I get error. For instance, "unknown mutation type" for using mutation
Probably several months late but I struggled with a similar issue, and eventually found the solution in https://github.com/championswimmer/vuex-module-decorators/issues/179
It talks about multiple requirements (which are summarised elsewhere)
The one that relates to this issue is that the file name of the module has to match the name you specify in the #Module definition.
In your case, if you rename your file from currentUser to CurrentUserStore' or change the name of the module toCurrentUser`, it should fix the issue.

How to use shorter path to get vuex contents?

In my vuex /store/state.js I have an export default that looks like this:
export default {
foo: {
bar:{
tar: {
info: 42
}
}
}
}
So, whenever I want to access info, I usually do in my methods like this;
methods: {
getInfo () {
return this.$store.state.foo.bar.tar.info
}
}
This is just for a demo purpose, and mine is actually a bit worse, but I ended up doing the same so, I tried minimize the code using a computed prop:
computed: {
info () {
return this.$store.state.foo.bar.tar.info
}
}
Now, I just call info but still, not sure if there is a better way to get values, because sometimes I just need to call info only one in a page, so I have to use the full path or create a computed property for it.
Is there any other way to do this
I always separate vuex into separated modules. For instance if you have store for foo module. I will create file named foo.js which contains
const fooModule = {
state: {
foo: {
bar: {
tar: {
info: 42
}
}
}
},
getters: {
info (state) {
return state.foo.bar.tar.info
}
},
mutations: {
setInfo (state, payload) {
state.foo.bar.tar.info = payload
}
},
actions: {
getInfo ({commit}, payload) {
commit('setInfo', payload)
}
}
}
export default fooModule
Then in your main index vuex, import the module like this way
import Vue from 'vue'
import Vuex from 'vuex'
import fooModule from './foo.js'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
fooModule
}
})
export default store
Then if you wanna get info, you just write your code like this
import { mapGetters } from 'vuex';
export default {
computed: {
...mapGetters([
'getInfo'
])
}
}
#jefry Dewangga has the the right idea but introducing mapGetters is unnecessary.
VueX by default includes namespacing for modules which allows us to load multiple modules into a store and then reference them with or without namespacing them and it'll figure the rest out.
For Instance if we have the structure of
|-- store
|-- Modules
|-- module1.js
|-- module2.js
|-- module3.js
|-- index.js
We can use index in such a way to bind all of our modules into our Vuex store doing the following:
import Vue from 'vue'
import Vuex from 'vuex'
import modules from './modules'
Vue.use(Vuex)
export default new Vuex.Store({
modules
})
An example of our module1 could be:
const state = {
LoggedIn: true
}
const mutations = {
LOGIN(state) {
state.LoggedIn = true;
},
LOGOFF(state) {
state.LoggedIn = false;
}
}
const actions = {}
export default {
state,
mutations,
actions
}
This in turn gives us the ability to say:
this.$store.commit('LOGIN');
Note that we haven't used any namespacing but as we haven't included any duplicate mutations from within our modules were absolutely fine to implicitly declare this.
Now if we want to use namespacing we can do the following which will explicitly use out module:
this.$store.module1.commit('LOGIN');
MapGetters are useful but they provide a lot of extra overhead when we can neatly digest out modules without having to continuously map everything, unless well we find the mapping useful. A great example of when MapGetters become handy is when we are working many components down in a large project and we want to be able to look at our source without having to necessarily worry about the frontend implementation.

Vuex2.0 how to configure and how to getters

Early today try vuex 2.1.2 vue:2.1.0, the directory structure is as follows
store.js:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import common from './common/store'
export default new Vuex.Store({
modules : {
common
}
})
mutations-types.js:
export const ADD_NUM = "ADD_NUM"
common/store.js:
import * as types from '../mutations-types'
const state = {
num : 1
}
const mutations = {
[types.ADD_NUM] : function(state){
state.num = state.num + 1;
},
}
export default {
state,
mutations
}
common/actions.js:
import * as types from '../mutations-types'
export default {
setNum : store => {
store.dispatch(types.ADD_NUM)
},
}
common/getters.js:
export default {
getNum : state => {
state.common.num
},
}
Then get the value of num in Hello.vue through getters
In the vue entry file main.js, a store is injected
run error:
Property or method "getNum" is not defined on the instance but
referenced during render
Why is this error reported? Does this directory structure and code correct?
First of all, I did not read the official documents
Using mapGetters solves the problem
THANKS #Potray
I refer to the official demo link