Recently I'm trying my best in redux, and I have seen a really good folder structure project, I tried to get the same structure, but the same way didn't work...
E.g. I've got a path something like that: ./src/_actions and inside this folder I've got "user.actions.js", "alert.actions.js", "index.js".
In alert.actions.js I've got something like that:
import { alertConstants } from "../_constants/alert.constants";
export const alertActions = {
success,
error,
clear,
};
function success(message) {
return { type: alertConstants.SUCCESS, message };
}
function error(message) {
return { type: alertConstants.ERROR, message };
}
function clear() {
return { type: alertConstants.CLEAR };
}
And I'd love to import all of them from one place like to the folder where path is "./../test.js":
import {alertActions} from "./../_actions";
import {useDispatch} from "react-redux";
export const test = () => {
const dispatch = useDispatch();
return (
<button onClick={() => dispatch(alertActions.success("test"))}> Click </button>
)
}
but I got something like "alertActions.success" is undefined. I don't know what I'm doing wrong.. In that project, index.js has been empty as well... that object supposed to export those all functions.. somebody know any solution? :(
You need to export the object after the functions are made. Usually they are hoisted, but in this case you are probably using strict mode and they are not. You have to either move the export object or better yet export all of them individually and then when you are importing them you should write:
import * as alertActions from 'youfile'
And if you want to export a whole object you should export it like:
export default alertActions
And then you need to import them like:
import alertActions from 'yourfile'
and access them:
alrtActions.error()
Related
I have a lot of minor components:
export const A = () => {...}
export const B = () => {...}
...
export default [A, B, ...];
After adding another component to the file, I might forget to add it to the export default [...]. By now you should see what the problem is.
How should I resolve this issue? Is it maybe possible to define a list that includes all exported functions?
I want to be able to iterate over all components in other files. Hence why it has to be a list they are grouped into.
origin file src/foo.js:
export const A = () => { ... };
export const B = () => { ... };
export const C = () => { ... };
Create an src/index.js as following:
import foos from './foo';
const allComponents = Object.values(foos);
export default allComponents;
From another file we'd:
import foos from 'src/foo';
foos[0]() // A()
foos[1]() // B()
...
EDIT: fixed the example code, needs to use values() not keys(), my bad
With some minor modifications, you can use import *. This gives you all of the named exports of a file, wrapped up into an object. If, for example, your old code was doing this:
import allComponents from 'someFile'
allComponents.forEach(component => {
// do something with the component
})
... instead do this:
import * as allComponents from 'someFile'
Object.values(allComponents).forEach(component => {
// do something with the component
})
As new exports are added to the file, this import statement will pull them in automatically, and so the default export array shouldn't be needed anymore.
I'm writing a react-redux code I defined an action to called in the componant, it's called addCart.
import axios from "axios"
import {GET_PLATS} from "./actionType"
export const getplats = () => dispatch => {
// 2-1 axions get the same path of back in app.use
axios.get("/plat-list").then(res => {
dispatch({
//2-2 same name in action type (after this go to make reducers)
type:GET_PLATS,
payload:res.data
})
})
}
export const addCart =( ) =>{
return (dispatch) => {
console.log("added To cart");
dispatch({
type:GET_PLATS,
})
}
}
then I've wrote this reducer:
import { GET_PLATS } from "../action/actionType"
//first create first main state
const initialState={
plats:[],
cmdElements:[]
}
export default function(state=initialState,action){
switch(action.type){
case GET_PLATS:
return{
...state,
plats:action.payload,
cmdElements:state.cmdElements
}
default :
return state
}
}
Then I called this action in a component**
import React, { Component } from 'react'
import { connect } from 'react-redux'
import {getplats,addCart } from '../../action/action'
import PropTypes from 'prop-types'
const { Meta } = Card
class PlatListeU extends Component {
componentDidMount(){
this.props.getplats()
}
render() {
return (
<div>
<Button type="primary" onClick={ () =>{
this.props.platListe.addCart()
} } >addTocart</Button>
</div>
)}
PlatListeU.propTypes = {
addCart:PropTypes.func.isRequired,
PlatListe:PropTypes.object.isRequired
}
const mapStateToProps =(state) =>{
return{
platListe:state.plats ,
cmdElements:state.cmdElements
}
}
export default connect(mapStateToProps,{ getplats,addCart}) (PlatListeU)
But when I press on the button, I have this error message:
TypeError: this.props.platListe.addCart is not a function
Everything should be fine. I tried a lot of ways but the result is the same . Can anyone help me?
It's just this.props.addCart(). You import the methods in the component, not in platListe. Thus the error.
For the other error:
it looks like your reducers are mapped correctly. so state.moviesReducer is always defined.
if your initial list of items doesn't even load correctly, means your items object are causing the error.
if your initial list loads correctly, and the error occurs only after you dispatch the action, means your update() is mutating your state shape.
I don't know where you are getting this update function. but i am guessing you should just return{items:update(..)}
This is how I would go about debugging your code.
I think it is just this.props.addCart()
I believe you just want this.props.addCart(). The key platListe exists in your state object, it does not have any methods attached to it. You import the standalone methods at the top of your component.
I am building an app using redux and react-native.
I am curious about a pattern which I use. I have encountered no downsides however I haven't seen it in any tutorials which makes me wonder why nobody does it.
Instead of passing action creators as props in the connect function like
connect(mapStateToProps,{ func1, func2 })(Component);
I imported the app store inside of the module where I declare the functions in the first place:
import { AppStore } from '../App';
const actionCreator = () => {
doSomethng();
appStore.dispatch({ type: 'Action' });
};
This to me makes it easier to do async actions because I need no middleware:
import { AppStore } from '../App';
const actionCreator = async () => {
await doSomethng();
appStore.dispatch({ type: 'Action' });
};
I did this because of the js-lint error 'no-shadow'. It made me realise that in order to use it I had to import the action creators in the component file, and then pass it as a prop to the connect function in order for the action creator to have access to dispatch.
import { actionCreator1, actionCreator2 } from './actionCreators';
const myComponent = (props) => {
const { actionCreator1, actionCreator2 } = props; //shadowed names
return (
<Button onPress={actionCreator1} />
);
};
export default connect({}, { actionCreator1, actionCreator2 })(myComponent)
In my version I just import it once but do not pass it to connect. This eliminates the need to shadow names.
import { actionCreator1, actionCreator2 } from './actionCreators';
const myComponent = (props) => {
return (
<Button onPress={actionCreator1} />
);
};
export default connect({})(myComponent)
I like that you try to find your own solutions to your specific problems. It's the sign of an engineer, just in this case this isn't the solution.
I think the idea of how Redux teaches you to do things is not intended to be canonized. You have the ability to put a dispatcher on your props because it allows things to be transparent, meaning that things are bound outside of your class and injected in. You have hidden your store dependency by directly referencing it in some other files. It's no longer as obvious how your application works with regards to the workflow. Another react developer would be confused, I suppose that's the major downside.
If you're ok with those aspects what you're doing is fine. Fine as in, it gets the job done, but not "fine" in that it embraces concepts like Single Responsibility Principle
Currently working with Redux and was wondering if there was a way to require in multiple modules into a single file, which is then exported again as a single module?
For example, in my actions/bookmark.js I group all actions related to bookmarks accordingly:
module.exports = {
fetchBookmarkList: () => {
return {
type: 'FETCH_LIST'
}
},
fetchBookmark: () => {
return {
type: 'FETCH_BOOKMARK'
}
}
}
Then in my actions/index.js file, I require in all groups of actions (which will include bookmark actions as well as others). Then I would like to export the entire file as a single module.
Schematically I had something like this in mind (obviously this code does not work):
actions/index.js:
module.exports = {
require('./bookmark');
require('./tags');
}
The reason that I want to do this is so that I only have to import a single action file that contains all my actions (i.e. the actions/index.js file):
Example component:
import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../actions';
class BookmarkList extends Component {
constructor(props) {
super(props);
this.props.fetchBookmarkList();
}
render() {
return (
<div></div>
);
}
}
export default connect(null, actions)(BookmarkList);
I see that you es6 modules syntax in components then, why not in your redux files?
export const fetchBookmarkList = () => {
return {
type: 'FETCH_LIST'
}
};
export const fetchBookmark = () => {
return {
type: 'FETCH_BOOKMARK'
}
}
Based on this reference I think it could be possible to re-export everything like this:
export * from './bookmark'
export * from './tags;
But haven't tried it and I could be wrong.
I would NOT recommend you to pass all the actions to mapDispatchToProps, only the actions needed by your component
But you could just use in actions/index.js:
Using the spread operator:
module.exports = {
...require('./bookmark');
...require('./tags');
}
And in ES6 syntax:
actions/index.js:
export * from './bookmark'
export * from './tags'
I cant get why following approach doesn't work:
constants.js
import { createConstants } from '../utils';
export default createConstants(
'LOGIN_REQUEST',
'LOGIN_SUCCESS',
'LOGIN_FAILURE',
'LOGOUT',
'FETCH_DATA_REQUEST',
'RECEIVE_DATA'
);
utils.js
import React from 'react';
export function createConstants(...constants) {
return constants.reduce((acc, constant) => {
acc[constant] = constant;
return acc;
}, {});
}
Next i want to import LOGIN_REQUEST for example as redux action.
import { LOGIN_REQUEST, LOGIN_SUCCESS, LOGIN_FAILURE, LOGOUT } from '../constants';
But i'm getting undefined each time for all imported constants.
It works only when i'm defining like this:
export const LOGIN_REQUEST = 'LOGIN_REQUEST';
Maybe somebody has some ideas?
Your first approach is called a default export. It doesn't work because the syntax you're using is not correct.
From the MDN export entry, that's how you write a default export:
// module "my-module.js"
export default function cube(x) {
return x * x * x;
}
Your second approach is called named export and it works because it has the right syntax. Again from MDN:
export const foo = Math.sqrt(2); // exports a constant
Hope it helps.
Export doesnt work like that. You can try something like:
import allConstants from '../constants';
Then use a constant like:
allConstants.LOGIN_REQUEST