Redcuers returning undefined in reactJS - reactjs

I have a problem with my dispatch.
Somehow it returns undefined even tho when I loged value of the input i want to pass I got the correct value.
Here is my reducer.
case actionTypes.ADD_COMMENT:
return {
...state,
posts : [
...posts,
{
comment : action.payload.comment,
}
]
}
export const addComment = (payload : any) => {
return {
type: actionTypes.ADD_COMMENT,
payload
}
}
And here is how i m passing the value to the dispatch.
if (commentValue) {
let commentVal = commentValue.value
console.log('--------commentVal', commentVal);
dispatch(actions.addComment({commentVal}))
}
Any suggestions?

It should be
dispatch(action.addComment({comment: commentVal}))
since you are accessing the comment property on the payload in your reducer

Related

get undefined in first render and cant get data

in this code I got undefined in first render but after that I can get the data
what is the problem?
action
export const getPlanPackage = () => async (dispatch) => {
const { data } = await getMyPlan();
return await dispatch({ type: "SET_PLAN_PACKAGE", payload: data.data });
};
reducer
const initialState = {
planPackage: [],
};
export const packagesReducer = (state = initialState, action) => {
switch (action.type) {
case "SET_PLAN_PACKAGE":
return {
...state,
planPackage: action.payload,
};
default:
return state;
}
};
const { planPackage } = useSelector((state) => state.packagesReducer);
const getDefaultOption = () => {
switch (planPackage?.month) {
case 1:
return 0;
case 6:
return 1;
case 12:
return 2;
default:
return planPackage?.month;
}
};
// OPTIONS
const [userPackage, setUserPackage] = useState(
userOptions[getDefaultOption()] || userOptions[0]
);
console.log(getDefaultOption());
result >>>>
undefined
undefined
undefined
undefined
undefined
1
1
1
1
So here I want to get a number from getDefaultOption() But when I refresh the page it gave me undefiend at first and I cant get the number and showing the data
I am going for a swing in the dark as I cant see the rest of your code, but it looks like month simply does not exist until it comes back from the server.
Your initial state is an empty array but the server returns an object with a month property instead if I am seeing correctly?
In that case you could either A, set the initialState an object with a similar state to what you expect back from the server but with a value of your choosing like so:
const initialState = {
planPackage: { month: 1 }, //set the initial value here
};
Or later in your code it looks like you want to perform a fall back here userOptions[getDefaultOption()] || userOptions[0]. In which case since you have your initial state as an array, unless you do planPackage?.length on the first call it will never be nullish.
This [] === true as is this [1,2] === true however this is false []?.length === false but this is true [1,2]?.length === true. I used ?.length because as I said it looks like you're getting back an object from const { data } = await getMyPlan(); and not an array, and objects don't have the length prototype.
So based on that you may want to do something like this?
const [userPackage, setUserPackage] = useState(
typeof getDefaultOption() === 'undefined' ? userOptions[0] : userOptions[getDefaultOption()]
);
Here we definily check if you get anything back from getDefaultOption() before passing it to userOptions because in it's current form userOptions[getDefaultOption()] // undefined will not fall back to || userOptions[0]. The check needs to be performed before being passed to userOptions[0]

React-Redux , issues reading an object fetched through redux thunk

I have a redux action / reducer that looks like the following.
Action:
export function loadServerInfo() {
return (dispatch) => axios.get(`${config.SERVER}/redis/server/info`).then(res => {
if (res.status == 200) {
dispatch(fetchServerInfo(res.data))
}
}).catch(err => {
})
}
export function fetchServerInfo(payload) {
return {
type: GET_SERVER_INFO,
payload
}
}
Reducer:
const defaultState = {
decodedRedisKey: {},
keyDecoded: false,
serverInfo: {}
}
const redisReducer = (state = defaultState, action: Action) => {
switch (action.type) {
case GET_REDIS_KEY_INFO: {
return {
...state,
decodedRedisKey: action.payload
}
}
case REDIS_KEY_DECODED: {
return {
...state,
keyDecoded: action.payload
}
}
case GET_SERVER_INFO: {
console.log(action.payload) //this is fired and logs the proper data, which is an object
return {
...state,
serverInfo: action.payload
}
}
default:
return {
...state
};
}
}
export default redisReducer;
Then I have a component connected and mapped to redux. Those are the connection parameters
const mapStateToProps = (state) => state;
function mapDispatchToProps(dispatch) {
return {
loadServerInfo: async () => {
dispatch(loadServerInfo());
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(UsersContainer);
And after that, I try to call the fetch, and get the data.
Problem is that the format of the object is as follows:
serverInfo: {
Server : {
uptime_in_days: "100",
version: "1.0.0"
}
}
My prop is firing on useEffect
React.useEffect(() => {
getUsersToken();
props.loadServerInfo();
console.log(process.env.REACT_APP_ENV)
}, []);
If i put it in a useEffect, first it logs undefined and afterward it loads
React.useEffect(() => {
console.log("server info")
console.log(props.redisReducer.serverInfo)
console.log(props.redisReducer.serverInfo.Server)
// console.log(props.redisReducer.serverInfo.Server.uptime_in_days) , if i uncomment this it crashes
}, [props.redisReducer.serverInfo])
So im having issues rendering the uptime_in_days value
I have tried doing this
{props.redisReducer.serverInfo != undefined && !displayServerInfo != undefined ?
<div className="basic-server-info-data">
<p><img src={redisLogo} /></p>
{/* <p>Connected Clients: <i>{serverInfo.Clients.connected_clients} </i></p> */}
{/* <p>Memory usage: <Progress type="circle" percent={memoryUsageStats} width={50} /> </p> */}
<p>Tokens (displayed): <i>{usersToken.length}</i></p>
<p>Uptime: <i>{props.redisReducer.serverInfo.Server.uptime_in_days} days</i></p>
</div>
:
null
}
It keeps crashing in the Uptime line, even tho im doing a check if its not undefined
Cannot read property 'uptime_in_days' of undefined
I tried changing the render condition to
props.redisReducer.serverInfo != undefined && !displayServerInfo != undefined && props.redisReducer.serverInfo.Server.uptime_in_days != undefined
But nothing changes.
How can I render that value?
EDIT: I have noticed this error
Warning: Can't perform a React state update on an unmounted component.
This is a no-op, but it indicates a memory leak in your application.
To fix, cancel all subscriptions and asynchronous tasks in a useEffect
cleanup function.
in my useEffect
Issue
The issue is that all your null checks start with the always defined state, props.redisReducer.serverInfo
const defaultState = {
decodedRedisKey: {},
keyDecoded: false,
serverInfo: {} // <-- defined!
}
state.serverInfo is always a defined object, so console.log(props.redisReducer.serverInfo) and console.log(props.redisReducer.serverInfo.Server) will always log, and the condition props.redisReducer.serverInfo != undefined will always be true.
You neglect to do a null check on props.redisReducer.serverInfo.Server before accessing the uptime value
props.redisReducer.serverInfo.Server.uptime_in_days
I'm guessing your UI is blowing up on the initial render before state is populated.
Solutions
Use Optional Chaining to handle the null check on Server being possibly undefined still.
props.redisReducer.serverInfo.Server?.uptime_in_days
Use conventional null checks
props.redisReducer.serverInfo.Server &&
props.redisReducer.serverInfo.Server.uptime_in_days

Cannot convert undefined or null to object : Next.js || React

Currently receiving a error stating Cannot convert undefined or null to object
The data the app is looking for comes from initial props.
I assume on the initial check no data is present, so it throws that error.
Would this be solved with an async/await ?
The initial posts_mentions is defaulted as an empty object
Here is the error image:
Here is the current code snippet
const { posts_mentions: postsMentions } = useData();
const data = Object.keys(postsMentions).map(label => {
return {
name: shortName(label),
posts: postsMentions[label].posts,
mentions: postsMentions[label].mentions
}
})
async function something(){
const { posts_mentions: postsMentions } = await useData();
const data = Object.keys(postsMentions).map(label => {
return {
name: shortName(label),
posts: postsMentions[label].posts,
mentions: postsMentions[label].mentions
}
})
}
Yes. Try adding await before useData(). And if this is all part of bigger function than mark it as async. How does the useData() look? Is something async in it?

UseEffect not triggering when used with MaterialTopTabNavigator

This is my first time using this platform to ask questions so please pardon me if my question does not seem well developed.
brief introduction
what I am trying to achieve is a dynamic Tab navigator, whereby the number of tabs changes depending on the number of elements in an array where this array changes in the number of elements over time, i.e :
{
userIds : [1,2,3,4,5,6]
}
will render a tab navigator with 6 tabs
I am using react-redux for managing state and I have been following this tutorial on youtube just for your information: https://www.youtube.com/watch?v=9boMnm5X9ak&list=PLC3y8-rFHvwheJHvseC3I0HuYI2f46oAK
context
in the main code snippet the action FetchMonthlyTransIdAct() is being dispatched, this consist of 2 actions being dispatched in order :
RequestMonthlyTransaction → FetchSuccess or FetchFail
(as per mentioned in FetchMonthlyTransIdAct.js, ) the initial state is as follows and the changes each action does :
{
loading : false
Id : []
error : ''
}
{
loading : true //when RequestMonthlyTransaction is dispatched
Id : []
error : ''
}
{
loading : false // When FetchSuccess is dispatched after RequestMonthlyTransaction
Id : [1,2,3,4,5,6]// When FetchSuccess is dispacthed after RequestMonthlyTransaction
error : ''
}
{
loading : false //when FetchFail is dispacthed after RequestMonthlyTransaction
Id : []
error : 'some error message here' //when FetchFail is dispatched after RequestMonthlyTransaction
}
problem
so the problem that I am currently facing is that useEffect does not seem to trigger when I am rendering components with navigationContainer/ tab.navigator
here is the snippet of my code, I have narrowed down the source of the problem between asterisks
const Tab = createMaterialTopTabNavigator();
const mapStateToProps = state => {
return {
userData: state.MonthlyEntry
}
}
const mapDispatchToProps = dispatch => {
return {
FetchMonthlyTransId: () => dispatch(FetchMonthlyTransIdAct())
}
}
const EntryTabNavigator = ({userData, FetchMonthlyTransId}) => {
useEffect (() => {
FetchMonthlyTransId()
}, [])
console.log(userData.Id)
if (userData.loading || userData.error != '') {
return <View/>
} else {
return(
**************************************************************************************
<NavigationContainer independent = {true}>
<Tab.Navigator swipeEnabled = {true} tabBarOptions = {{scrollEnabled:true, tabStyle:{width:120}}}>
{userData.Id.map((data) => {return (<Tab.Screen key = {data.toString()} name = {data.toString()} component = {MonthlyTransactions} initialParams={{id:data.toString()}}/>)})}
</Tab.Navigator>
</NavigationContainer>
**************************************************************************************
)
}
};
export default connect(mapStateToProps, mapDispatchToProps)(EntryTabNaviga
the error message simply that there was no screen for tab navigator to render (due to userData.Id being an empty array when it should not)
based on the console.log(userData.Id)
the expected output should be Array [1,2,3,4,5,6]
but the actual output was Array [] which indicates that the useEffect was not triggered
I have tried replacing the snippet of code between the astericks with
<View><Text>{userData.Id}</Text><View> and it was able to render as expected (returning a screen with the string representation of the array as the text), hence leading me to identify that the code snippet between the astericks is the problematic portion. I have also tried adding a console.log statement within useEffect and it does not output anything into the console when I have the code snippet in asterisks, however it does output into the console when I replaced the snippet of code between the astericks with <View><Text>{userData.Id}</Text><View>
should there be a similar problem to this that has already been asnwered, it would be much apppreciated if you could direct me to it, it would also be great if you could point me to resources to improve my knowledge with redux (prefreably beginner friendly) ! additional reference code (reducer and action) is below
Thank you in advance
FetchMonthlyTransIdAct.js
const requestMonthlyTransaction = () => {
return {
type: "REQUEST_MONTHLY_TRANSACTION",
}
}
const fetchSucess = (ids) => {
return {
type: "FETCH_SUCCESS",
payload: ids,
}
}
const fetchFail = (error) => {
return {
type: "FETCH_FAILURE",
payload: error,
}
}
export const FetchMonthlyTransIdAct = () => {
return (dispatch) => {
dispatch(requestMonthlyTransaction())
async function getId() {
return require('../../data/DummyId.js').id //returns [1,2,3,4,5,6]
}
getId().then(
id => dispatch(fetchSucess(id))
).catch(
error => dispatch(fetchFail(error))
)
}
}
FetchMonthlyTransIdRed.js
const initialState = {
loading:false,
Id : [],
error:''
}
const FetchMonthlyTransactionIdRed = (state = initialState, action) => {
switch (action.type){
case "REQUEST_MONTHLY_TRANSACTION":
return {
...state,
loading: true,
}
case "FETCH_SUCCESS":
return {
...state,
loading: false,
Id: action.payload
}
case "FETCH_FAILURE":
return {
...state,
loading: false,
error: action.payload
}
default: return state;
}
}
export default FetchMonthlyTransactionIdRed;
after much tinkering, I manage to find a solution (or a workaround rather) to the problem. which is to add an initial element in the array of the Id attribute in the initial state in FetchMonthlyTransIdRed.js, that will allow the first render of the navigation component to occur without issues, and subsequently in the next re-render when FetchMonthlyTransId is dispatched Id is then updated with the array that I have imported
Use React Navigation's useFocusEffect, e.g.:
import { useFocusEffect } from '#react-navigation/native';
function Profile({ userId }) {
const [user, setUser] = React.useState(null);
useFocusEffect(
React.useCallback(() => {
const unsubscribe = API.subscribe(userId, user => setUser(user));
return () => unsubscribe();
}, [userId])
);
return <ProfileContent user={user} />;
}

My redux thunk Axios calls return empty objects in my Redux store

I am using tmdb and redux-thunk to make async calls and return the data. I've tried every way possible and only empty objects show up in my store even though when I log the results I see the data there.
I tried to map through the results with no luck. If I return it by the index for example (example[0]) it does show the results of the first index.
Screenshots of store and console - https://imgur.com/a/zrv0Sjm
export const fetchVideoKeys = urlArray => {
return dispatch => {
dispatch(isLoading(true));
axios
.all(urlArray)
.then(
axios.spread((top, pop, up, now) => {
console.log(top)
dispatch(getVideoKeys(top));
})
);
};
};
const initialState = {
videoKeys: {
topRated: [],
popular: [],
upcoming: [],
nowPlaying: [],
}
};
export default function VideoTrailerReducer(state=initialState, action) {
switch (action.type) {
case VideoTrailerActionTypes.GET_VIDEO_KEYS:
return {
videoKeys: {
topRated: [action.payload]
}
}
default:
return state;
}
}
useEffect(() => {
movieIds.popular.length > 1 &&
movieIds.topRated.length > 1 &&
movieIds.upcoming.length > 1 &&
movieIds.nowPlaying.length > 1 &&
setTimeout(() => {
dispatch(
fetchVideoKeys([
createUrls(movieIds.topRated, videoUrls),
createUrls(movieIds.popular, videoUrls),
createUrls(movieIds.upcoming, videoUrls),
createUrls(movieIds.nowPlaying, videoUrls)
])
);
}, 1000);
}, [
movieIds.topRated,
movieIds.popular,
movieIds.nowPlaying,
movieIds.upcoming
]);
export const getVideoKeys = data => {
return {
type: VideoTrailerActionTypes.GET_VIDEO_KEYS,
payload: data
}
}
I expect the store to show the results but is only returning empty objects.
Based on your screengrab, I expect you wish to dispatch data.results from your ajax response. Right now you are dispatching the promise.
Try playing around with console.log(top.data.results)
Your code example assumes that your url list will have just 4 array items, so where you have this:
axios.spread((top, pop, up, now) => {
top will be the response from the first url passed.
A codepen calling your api might help.
[Also you're exposing your api key in the image]

Resources