Redux state updated but component not re-rendered (while using promise) - reactjs

I am using React/Redux.
The main issue is that when i use Promise then component is not re-rendered, whereas the code is working fine when promise code is not used.
Action Creator
const updateColor = colorobj => {
return dispatch =>
new Promise(function(resolve, reject) {
dispatch(fetchColorBegin());
axios
.post(config.APIURL.color.update, colorobj)
.then(response => {
const data = response.data;
if (data.errorno !== 0) {
dispatch(fetchColorFailure(data.errormsg));
reject(data.errormsg);
} else {
dispatch(updateColorSuccess(colorobj));
resolve('Color Updated');
}
})
.catch(error => {
dispatch(fetchColorFailure(error.message));
reject(error.message);
});
});
};
Reducer
case UPDATE_COLOR_SUCCESS:
const todoIndex = state.data.findIndex(todo => todo.id === action.payload.id);
return update(state, {
loading: { $set: false },
data: { [todoIndex]: { $merge: action.payload } },
error: { $set: null}
});
Component
the state is updated but the component is not updated.
const handleEditOk = values => {
let colorobj = {
id: state.updateData.id,
colorname: values.colorname,
colorcode: values.colorcode,
};
dispatch(updateColor(colorobj))
.then(response => {
message.success(response);
onCancel();
})
.catch(error => {
message.error(error);
});
};
The component update itself only on commenting the promise code.
The problem now is that it is not showing success/failure message.
const handleEditOk = values => {
let colorobj = {
id: state.updateData.id,
colorname: values.colorname,
colorcode: values.colorcode,
};
dispatch(updateColor(colorobj))
// .then(response => {
// message.success(response);
// onCancel();
// })
// .catch(error => {
// message.error(error);
// });
};
Kindly suggest.

Related

React updating data of an array but changes not appears

I have a array of groups which is brought from API, and is displayed on a table..
return(
<Table
data={props.data}
columns={columns}
noHeader={true}
/>
)
const mapStateToProps = state => ({
data: state.Table.arrayGroups,
})
In this table I have a column that has a button that enable and disable a group, that calls this action:
export const handleStatus = (data, status, id, endPoint, ActionType) => {
let index = data.findIndex( array => array.id === id);
console.log(index)
if (status) {
console.log('entrei disable')
data[index].enable = false
console.log(data)
return dispatch => {
httpPut(`${endPoint}/${id}/disable`)
.then(resp => {
return [
dispatch({
type: ActionType,
payload: data
})
]
})
.catch(error => {
console.log(error)
})
}
}
else {
console.log('entrei enable')
data[index].enable = true
return dispatch => {
httpPut(`${endPoint}/${id}/enable`)
.then(resp => {
return [
dispatch({
type: ActionType,
payload: data
})
]
})
.catch(error => {
console.log(error)
})
}
}
}
On this action I'm basically getting data array and changing a value inside of it.. and update the arrayGroups.. like this :
case 'MODIFIED_GROUPS':
return { ...state, arrayGroups: action.payload }
the issue is : after doing it table continuous displaying the previous array Data
Connect by react-redux is a PureComponent . What it means is that unless the props change it doesn't trigger a re-render. And it performs a shallow equality and reference check.
Since in your case you are mutating the data, the update isn't triggereing.
Clone the data obejct and update it
export const handleStatus = (data, status, id, endPoint, ActionType) => {
let index = data.findIndex( array => array.id === id);
console.log(index)
const newData = [...data]; // shallow cloning data
if (status) {
console.log('entrei disable')
newData[index].enable = false
console.log(newData);
return dispatch => {
httpPut(`${endPoint}/${id}/disable`)
.then(resp => {
return [
dispatch({
type: ActionType,
payload: newData
})
]
})
.catch(error => {
console.log(error)
})
}
}
else {
console.log('entrei enable')
newData[index].enable = true
return dispatch => {
httpPut(`${endPoint}/${id}/enable`)
.then(resp => {
return [
dispatch({
type: ActionType,
payload: newData
})
]
})
.catch(error => {
console.log(error)
})
}
}
}

React native - React Hook useEffect has a missing dependency:'getAllPost'. Either include it or remove the dependency array.",

I am new in react native and try to call two api from useEffect but it give me this error every time React Hook useEffect has a missing dependency: 'getAllPost'. Either include it or remove the dependency array.
Here is my code
export default function Home({navigation}) {
const [arrCat, setArrCat] = useState([]);
const [arrPost, setArrPost] = useState([]);
const [isLoading, setLoding] = useState(false);
function getAllCategory() {
setLoding(true);
let apiResponse = ApiManager.GET('category/all', [], 'GET');
apiResponse
.then(response => {
let responseJson = response[1];
let status = response[0];
setLoding(false);
let message =
responseJson.message != null
? response.message
: 'Something went wrong';
if (status === 200) {
setArrCat([...responseJson.data]);
getAllPost();
}
setTimeout(function() {
if (message != null) {
Toast.showWithGravity(message, Toast.LONG, Toast.BOTTOM);
}
}, 120);
})
.catch(error => {
console.error(error);
Toast.showWithGravity(error, Toast.LONG, Toast.BOTTOM);
setTimeout(function() {
setLoding(false);
}, 60);
});
}
function getAllPost() {
GetLocation.getCurrentPosition({
enableHighAccuracy: true,
timeout: 15000,
})
.then(location => {
console.log(location);
const dictData = {
lat: '-37.81400200-33.865143', //location.latitude,
lang: '144.9546943', //location.longitude,
record_count: '0',
};
console.log(dictData);
let apiResponse = ApiManager.POST(
'post/getRecommendedPost',
dictData,
'POST',
);
apiResponse
.then(response => {
let responseJson = response[1];
let status = response[0];
if (status === 200) {
console.log(responseJson);
setArrPost(oldValue => [...oldValue, ...responseJson.data]);
console.log(arrPost);
} else {
// console.error(responseJson);
Toast.showWithGravity(
responseJson.message,
Toast.LONG,
Toast.BOTTOM,
);
}
})
.catch(error => {
// console.error(error);
Toast.showWithGravity(error.message, Toast.LONG, Toast.BOTTOM);
// setTimeout(function() {
// setLoding(false);
// }, 60);
});
})
.catch(error => {
// const {code, message} = error;
// console.warn(code, message);
Toast.showWithGravity(error.message, Toast.LONG, Toast.BOTTOM);
});
}
useEffect(() => {
console.log('Home screen mounted');
getAllCategory();
// getAllPost();
}, []);
return ( ....)
}

I am getting Cannot read property 'then' of undefined while calling the api in react

I am getting TypeError: Cannot read property 'then' of undefined when calling the api in react.js and redux.
my component did mount function is -
componentDidMount() {
window.scrollTo(0, 0);
var requestedId = this.props.match.params.id;
this.props.fetchCategoryJoblist(requestedId).then(() => {
this.setState({ loading: false });
});
}
I am getting can not read property of then at this line this.props.fetchCategoryJoblist(requestedId).then(())
My componentDidMount function -
componentDidMount() {
window.scrollTo(0, 0);
var requestedId = this.props.match.params.id;
this.props.fetchCategoryJoblist(requestedId).then(() => {
this.setState({ loading: false });
});
}
My action.js file -
// code to get job listing based on category
export function setCategoryJoblist(categoryjoblist) {
return {
type: SET_CATEGORY_JOBLIST,
categoryjoblist
};
}
export function fetchCategoryJoblist(requestedId) {
var apiUrl = `http://18.207.190.61:4000/getJobByCategory/${requestedId}`;
return dispatch => {
fetch(apiUrl)
.then(res => res.json())
.then(data => dispatch(setCategoryJoblist(data.Jobs)));
};
}
So how can I use then method in componentDidMount Method ?
Your fetchCategoryJobList
export function fetchCategoryJoblist(requestedId) {
var apiUrl = `http://18.207.190.61:4000/getJobByCategory/${requestedId}`;
return dispatch => {
// see here
fetch(apiUrl)
.then(res => res.json())
.then(data => dispatch(setCategoryJoblist(data.Jobs)));
};
}
Maybe the problem is in here
export function fetchCategoryJoblist(requestedId) {
var apiUrl = `http://18.207.190.61:4000/getJobByCategory/${requestedId}`;
return dispatch => {
// you don't have return here, so your call to API is won't return a promise call CMIIW
return fetch(apiUrl)
.then(res => res.json())
.then(data => dispatch(setCategoryJoblist(data.Jobs)));
};
}

useState does not support a second callBack, what could be the easy fix?

This is my useEffect
useEffect(() => {
let pageId =
props.initialState.content[props.location.pathname.replace(/\/+?$/, "/")]
.Id;
if (props.initialState.currentContent.Url !== props.location.
setCurrentContent({ currentContent: { Name: "", Content: "" } }, () => {
fetch(`/umbraco/surface/rendercontent/byid/${pageId}`, {
credentials: "same-origin"
})
.then(response => {
if (response.ok) {
return response.json();
}
return Promise.reject(response);
})
.then(result => {
setCurrentContent({
currentContent: { Name: result.Name, Content: result.Content }
});
});
});
}
}, []);
I have tried things like useCallback/useMemo but yet no luck, I'm sure this is a simple fix but I must be missing the bigger picture, thanks in advance.
What you can do is write an effect that checks if the currentContent state is changed and empty and takes the necessary action. You would however need to ignore the initial render. Also unline setState in class components you don't pass on the state value as object instead just pass the updated state
const ContentPage = props => {
const [currentContent, setCurrentContent] = useState({
Name: props.initialState.currentContent.Name,
Content: props.initialState.currentContent.Content
});
const initialRender = useRef(true);
useEffect(() => {
let pageId =
props.initialState.content[props.location.pathname.replace(/\/+?$/,
"/")]
.Id;
if (
initialRender.current &&
currentContent.Name == "" &&
currentContent.Content == ""
) {
initialRender.current = false;
fetch(`/umbraco/surface/rendercontent/byid/${pageId}`, {
credentials: "same-origin"
})
.then(response => {
if (response.ok) {
return response.json();
}
return Promise.reject(response);
})
.then(result => {
setCurrentContent({ Name: result.Name, Content: result.Content });
});
}
}, [currentContent]);
useEffect(() => {
if (props.initialState.currentContent.Url !== props.location) {
setCurrentContent({ Name: "", Content: "" });
}
}, []);
...
};
export default ContentPage;

Async Actions resolve before fetch result is retrieved

I'm using Redux with redux-thunk to retrieve categories from an API. I have an action called viewCategory that depends on having categories in the store state.
I used the example of fetching Reddit posts from the Redux site:
https://redux.js.org/advanced/asyncactions#actions-js-asynchronous
The problem I have is that when I call viewCategory the promise thinks it's resolved when REQUEST_CATEGORIES is dispatched and not RECEIVE_CATEGORIES. So if log my state in the then statement I have an
empty list of categories.
export function viewCategory(urlKey) {
return (dispatch, getState) => {
dispatch(fetchCategoriesIfNeeded()).then(() => {
let state = getState();
console.log(state); // should have categories
let categories = [...state.categories.mainCategories,
...state.categories.specialCategories];
let matchCategory = categories.find((category) => {
return category.custom_attributes.find(x => x.attribute_code === "url_key").value === urlKey;
});
dispatch({
type: Categories.VIEW_CATEGORY,
category: matchCategory
});
});
};
}
The functions that decide if categories should be fetched at all:
function shouldFetchCategories(state) {
const categories = state.categories;
if(categories.isFetching || categories.mainCategories.length > 0) {
return false;
} else {
return true;
}
}
export function fetchCategoriesIfNeeded() {
return (dispatch, getState) => {
if(shouldFetchCategories(getState())) {
return dispatch(fetchCategories());
} else {
return Promise.resolve();
}
};
}
The function that contains the actual fetch call:
function fetchCategories() {
return (dispatch, getState) => {
dispatch(requestCategories());
const {locale} = getState().settings;
return fetch(`${BASE_URL}/categories/list`, {
method: "POST",
headers: {
"Accept-Language": locale
},
body: "Not interesting for stackoverflow"
})
.then(response => response.json())
.then(json => {
if(json !== undefined && json.items){
dispatch(receiveCategories(json.items));
}
});
};
}
The functions where I dispatch types REQUEST_CATEGORIES & RECEIVE_CATEGORIES:
function requestCategories() {
return {
type: Categories.REQUEST_CATEGORIES
};
}
function receiveCategories(result) {
const mainCategories = result.filter(category => category.level === 2);
const subCategories = result.filter(category => category.level === 3);
const categories = mainCategories.map(category => {
let children = subCategories.filter(x => x.parent_id === category.id);
return {
...category,
children
};
});
let specialCategories = categories.splice(categories.length - 2, 2);
return {
type: Categories.RECEIVE_CATEGORIES,
categories: categories,
specialCategories: specialCategories,
receivedAt: Date.now()
};
}
Any idea what I am doing wrong here? If you need any extra code or information please let me know.

Resources