Getting rid of console logs in redux wrapper with Next.js - reactjs

Hey guys I just downloaded some source file from internet which uses redux thunk with Next.js in order to see how things work and then after running it with npm run dev the project runs successfully but then in console I keep getting this logs:
1. WrappedApp.getInitialProps wrapper got the store with state {
loginAndSignupReducer: [],
getCategoryReducer: { loading: false, err: false, data: [] },
MyStoryReducer: { loading: false, err: false, data: [] },
reportStoryReducer: { loading: false, err: false, data: [] },
getAllDetails: []
}
3. WrappedApp.getInitialProps has store state {
loginAndSignupReducer: [],
getCategoryReducer: { loading: false, err: false, data: [] },
MyStoryReducer: { loading: false, err: false, data: [] },
reportStoryReducer: { loading: false, err: false, data: [] },
getAllDetails: []
}
4. WrappedApp.render created new store with initialState {
loginAndSignupReducer: [],
getCategoryReducer: { loading: false, err: false, data: [] },
MyStoryReducer: { loading: false, err: false, data: [] },
reportStoryReducer: { loading: false, err: false, data: [] },
getAllDetails: []
}
These things get rendered first of all and so because of this. I also see them in page source as objects
I have shared an image below please refer to it, I rendered my id in <p> tag but then here I am seeing it as object.
Does anyone from where to get rid of them permanently?

This is most likely because you copy the code sample from the docs which sets debug to true when you create a wrapper:
export const wrapper = createWrapper<State>(makeStore, {debug: true});
Remove the debug property or set it to false to fix the issue
export const wrapper = createWrapper<State>(makeStore);
Live Demo

There are two reasons for this that I can think of, either the Debug Property is set to false during the wrapper creation. To Fix that, do this
// From This
const wrapper = createWrapper<RootState>(initializeStore, { debug: true })
// To This
const wrapper = createWrapper<RootState>(initializeStore, { debug: false })
// Or Rather
const wrapper = createWrapper<RootState>(initializeStore)
Or you might have some middleware like "logger" in your State. So if that's the case get rid of any middleware you don't need. Logger can be replaced with redux-devtools-extension

Related

Redux initial state in reducer not accepting new values

I'm running into a strange problem where the initial state in one of my reducers is not accepting new values. I've been able to add new values to this initial state easily, but for some reason now new initial state entries come back as undefined when I mapStateToProps.
//REDUCER
const initialState = {
(...cutting out a bunch of state here),
collectionSearchResults: {
results: {},
loading: false,
loaded: false,
error: ''
},
collectionImage: {
image: '',
loading: false,
loaded: false,
error: '',
},
collectionBeingEdited: {
collectionId: '',
loading: false,
complete: false,
error: '',
test: '',
},
removeReport: {
loading: false,
}
}
//INDEX of Component
const mapStateToProps = state => ({
(...cutting out a bunch of state here)
collectionBeingEdited: state.research.collectionBeingEdited,
removeReport: state.research.removeReport,
userInfo: state.account.myAccount.info,
})
//IN COMPONENT
console.log(this.props)
//result -> removeReport: undefined
InitialState of a reducer is not a reducer. As Martin suggested, you need to post your actual reducer.
I'm willing to bet that in one of your reducer cases its not returning the rest of the state:
case 'something':
return {
someKey: action.value
}
instead of:
case 'something':
return {
...state,
someKey: action.value
}
and thats why the property you're expecting doesnt exist.

Redux updating nested data [Immutable Update Patterns]

Can anyone help with this update pattern. I am not using any libraries like immer.
I have to update a nested object and the data looks like dis
Sample data
{
isFetching: false
data:{
nba : {
stack :{
1:[]
}
}
}
}
My Reducer
{
...state,
isFetching: false,
data: {
...state.data,
[action.payload.team]: {
...state[action.payload.team],
[action.payload.framework]: {
...state[action.payload.framework],
[action.payload.build]: action.payload.resp
}
}
}
};
I am able to update until second level but unable to update third child.
can anyone throw a light on where i am missing it.
I put a demo on codesandbox.
https://codesandbox.io/s/todos-0ygrs
Click on collapse and inner collapse items. I am logging the changes for the state in the console below. As you can see at last level, build numbers are getting replaced with the new one's.
Current Behaviour After you expand nba and all the three childs
{
nba: {
stack:{
3:[]
}
}
Expected Behaviour: After you expand stack and all the three childs
{
nba: {
stack:{
1:[],
2:[],
3:[]
}
}
}
You probably have to use a get helper because you may try to set a part of state that doesn't exist yet.
With the get helper you can set the state like this:
const { team, framework, build, resp } = action.payload;
const newState = {
...state,
isFetching: false,
data: {
...get(state, ['data']),
[team]: {
...get(state, ['data', team]),
[framework]: {
...get(state, ['data', team, framework]),
[build]: resp,
},
},
},
};
Somehow i figured out my mistake, Hope it helps someone in future
Initial state should not be null, it should be empty object and update pattern should be in this manner
{
...state,
isFetching: false,
data: {
...state.data,
[action.payload.team]: {
...state.data[action.payload.team],
[action.payload.framework]: {
...state.data[action.payload.team][action.payload.framework],
[action.payload.build]: action.payload.resp
}
}
}
};
if it fails, then try this way
let teamTemp = { ...state.data[action.payload.team]}
{
...state,
isFetching: false,
data: {
...state.data,
[action.payload.team]: {
...teamTemp ,
[action.payload.framework]: {
...teamTemp[action.payload.framework],
[action.payload.build]: action.payload.resp
}
}
}
};
I have forked my codesandbox and updated latest code.
Old Code: https://codesandbox.io/s/todos-0ygrs
New Code: https://codesandbox.io/s/todos-zqeki

Redux single state update

I receive the data for all lamps in one request.
(I can, however, receive each lamp data from the server individually).
The data I receive from the server looks like this.:
[
{
"id": "1",
"state": 'ON'
},
{
"id": "2",
"state": 'OFF'
},
{
...
},
...
]
In my app, this data will be stored in a single redux state. I use FlatList to render this data along with a simple Switch so that the user can turn each lamp ON or OFF.
When the user changes a lamp's state, a LOADING action will be dispatched and the whole lamps will show a spinner.
When the updated data is received from the server, a SUCCESS action will be dispatched, the redux state will be updated, the spinner will disappear and finally, the updated data will be shown.
Problem 1: When the user interacts with only one lamp, I don't want all lamps to go into LOADING state!
Problem 2: I never know how many lamps I will receive in my requests.
Desired Behaviour: Only the lamp, with which the user has interacted, must show a spinner and goes thrown the update process.
I need help with handling the redux states.
I hope this information helps. Below you can find my Rudcers for lightingInitReducer (getting data for all lamps) and lightingChangeStateReducer (changing the state of a lamp). isLoading is used for showing the spinner. Additionally, when the change state process was successful (LIGHTING_CHANGE_STATUS_SUCCESS is dispatched), the new data will be requsted from the server with an init request:
export const lightingInitReducer = (state = {
isLoading: false,
errMess: null,
info: {},
}, action) => {
switch (action.type) {
case ActionTypes.LIGHTING_INIT_SUCCESS:
return {
...state, isLoading: false, errMess: null, info: action.payload,
};
case ActionTypes.LIGHTING_INIT_FAILED:
return {
...state, isLoading: false, errMess: action.payload, info: {},
};
case ActionTypes.LIGHTING_INIT_LOADING:
return {
...state, isLoading: true, errMess: null, info: {},
};
default:
return state;
}
};
export const lightingChangeStateReducer = (state = {
isLoading: false,
errMess: null,
info: {},
}, action) => {
switch (action.type) {
case ActionTypes.LIGHTING_CHANGE_STATUS_SUCCESS:
return {
...state, isLoading: false, errMess: null, info: action.payload,
};
case ActionTypes.LIGHTING_CHANGE_STATUS_FAILED:
return {
...state, isLoading: false, errMess: action.payload, info: {},
};
case ActionTypes.LIGHTING_CHANGE_STATUS_LOADING:
return {
...state, isLoading: true, errMess: null, info: {},
};
default:
return state;
}
};
Check out immutability-helper: https://github.com/kolodny/immutability-helper
It's amazing. Reducers can get real messy with deeply nested states, and this lib helps tidy things up a lot.
For problem 1, here is an idea of how you could update a single lamp, and display a loading state for that one item:
You can use the index of the pressed list item from your FlatList and pass that along to the LOADING action that dispatches your server request. You can then use this index in your reducer to update that specific lamp in your state. Using the immutability-helper library, the reducer might look like this:
import update from 'immutability-helper';
case UPDATE_LAMP_REQUEST:
let newState = update(state, {
lamps: {
[action.index]: {
loading: { $set: true }, // turns on loading state for lamp at index
}
}
})
return newState;
Once the web request has complete, and your SUCCESS action has dispatched, you can then pass that same index from your FlatList to your reducer, and update the lamp in your state with the updated lamp from the server:
import update from 'immutability-helper';
case UPDATE_LAMP_SUCCESS:
let newState = update(state, {
lamps: {
[action.index]: {
loading: { $set: false }, // turn off loading
$set: action.lamp // set the new lamp state
}
}
})
return newState;
You'd then connect the "loading" field to the component responsible for a single list view item in your FlatList and use that value to hide / show the loading state.
As for problem 2, I'm not sure I understand the question.

Immutable object is not being set in state

The immutable object being returned is correct but this.setState({...}) does not seem to set it.
I've tried the various ways to set state and all seem to have failed.
state = {
onboarding3: fromJS({
selection: {
neverBeen: false,
noConvert: false,
both: false
},
noConvertOptions: {
dynamicCreative: false,
noPurchase: false,
abandoned: false
},
bothOptions: {
dynamicCreative: false,
noPurchase1: false,
noPurchase2: false
}
})
};
updateToggle = (field, option) => {
return () => {
const currentValue = this.state.onboarding3.getIn([field, option]);
const onboarding3 = this.state.onboarding3.setIn([field, option], !currentValue);
this.setState({ onboarding3 });
};
};
<Component
roundedSwitchFunc={this.updateToggle("noConvertOptions", "dynamicCreative")}
defaultChecked={onboarding3.getIn(["noConvertOptions", "dynamicCreative"])}
/>
It was an issue of event bubbling and the data not being in sync. The purpose of this component was for my state to mimic the store but since each component has their own 'store', it does not accurately mimic Redux.

How to return state of Redux reducers

For redux reducer step :
What if I only want to change one single property of initial_state. For example:
const INITIAL_STATE = {
signInInfo: {
signin: false,
name: "",
email: "",
...
},
changePassword: {
status: false,
...
}
...
};
Here I only want to set signInInfo.signin as true, currently , the only way I know is to input a complete "signInInfo" like :
case SIGNIN_USER:
return { ...state, signInInfo: action.payload.data };
action.payload.data is like:
{
signin: true,
name: "Qing",
email : ...
}
And another question is what if I want to set signInInfo.signin as false and meanwhile also need to change changePassword.status from false to true.
What should I do? Can anyone give me a hint?
Fairly simple (both questions):
case SIGNIN_USER: return {
...state,
signInInfo: {
...state.signInInfo,
signin: action.payload.signin
},
changePassword: {
...state.changePassword,
status: true
}
};

Resources