How to set object hook properly in React? - javascript

I have these states:
const [maintenanceTypeId, setMaintenanceTypeId] = useState(null);
const [maintenanceId, setMaintenanceId] = useState(null);
const [addedId, setAddedId] = useState({
mainId : null,
mainTypeId : null,
});
I set states in these functions:
//setMaintenanceTypeId
//setAddedId
const addNewMainTypesList = async () => {
try {
const { data } = await axios.post(`${serverBaseUrl}/insertRowtoMainTypes`, {
description: newMaintenanceList.description,
title: newMaintenanceList.title
});
setMaintenanceTypeId(data[0]?.id);
console.log("MaintenanceTypeId", maintenanceTypeId);
//console.log("inserted type id",data[0]?.id);
setAddedId({...addedId, mainTypeId : maintenanceTypeId});
} catch (err) {
throw err;
}
const maintenanceList = await getMainTypes();
// console.log("main list", maintenanceList);
setMaintenanceList(maintenanceList);
};
//setMaintenanceId
//setAddedId
const addNewMainTypes = async () => {
try {
const { data } = await axios.post(`${serverBaseUrl}/insertRowtoMain`, {
nodeid: newMaintenance.nodeid,
maintenancetype: newMaintenance.maintenancetype,
personnel: newMaintenance.personnel,
process: newMaintenance.process,
date: newMaintenance.date,
});
setMaintenanceId(data[0]?.id);
console.log("MaintenanceId", maintenanceId);
setAddedId({...addedId, mainId : maintenanceId});
//console.log("inserted main id",data[0]?.id);
} catch (err) {
throw err;
}
I am console logging the addedId state in a submitHandler.
const submitHandler = (e) => {
e.preventDefault();
addNewMainTypesList();
getMain();
getMainTypes();
addNewMainTypes();
console.log("addedId",addedId);
}
Here is the console. As you can see, I can not get the maintenanceTypeId. How can I fix this?

setState is an asynchronous function. In other words, it won't directly update a given state.
In your case setMaintenanceTypeId is not directly updating maintenanceTypeId.
In order, to make it update directly, use inside of it an anonymous function, like this:
setMaintenanceTypeId(mTypeId => data[0]?.id);
It would be also better if you do the same for setAddedId (though not mandatory):
setAddedId(addedId => {...addedId, mainTypeId : maintenanceTypeId});
Let me know if this still doesn't work.

Related

why i got an error in my handleClick async function?

i tried to add the display_1 and diplay_2 in my mutation variables and tried to console.log it but the output is (undefined, false, undefined) for the console.log(data,loading,error)
const CREATE_T09_SCREENSHOT = gql`
mutation
createT09ScreenShot(
$screenshot_window_1: String!,
$screenshot_window_2: String!,
) {
createT09ScreenShot(
screenshot_window_1: $screenshot_window_1,
screenshot_window_2: $screenshot_window_2,
) {
screenshot_window_1
screenshot_window_2
}
}
`;
const SaveLogsButton = () => {
const [createT09ScreenShot, { loading, error, data }] = useMutation(CREATE_T09_SCREENSHOT);
const handleClick = async () => {
const screenshotData = await saveImage();
if (screenshotData){
const { display_1, display_2 } = screenshotData;
createT09ScreenShot({
variables: {
screenshot_window_1: display_1,
screenshot_window_2: display_2,
},
});
}
console.log(data)
console.log(loading)
console.log(error)
};
i also tried to do this but it give me an error
const handleClick = async () => {
await saveImageFunction();
const { display_1, display_2 } = saveImage;
createT09ScreenShot({
variables: {
and here is the error
Unhandled Promise Rejection: TypeError: Right side of assignment cannot be destructured
I think you have some error inside handleclick function of saveImage destructurable object.
You need to replace your handleClick function code with this code:
const handleClick = async () => {
const screenshotData = await saveImageFunction();
const { display_1, display_2 } = screenshotData;
createT09ScreenShot({
variables: {
screenshot_window_1: display_1,
screenshot_window_2: display_2,
},
});
};

Accessing updated state inside the same function

I am having trouble accessing state after saving it, when calling the same function. My state is setup like this:
const perLanguageDefault = {
calculated_skill: null,
display_skill: null,
published: false,
premium: false,
id: null,
};
const [perLanguage, setPerLanguage] = useState(perLanguageDefault);
I have a save function inside one of my components as such:
const _savePerLanguageArticle = async () => {
if (perLanguage.id === null) {
await _createPerLanguage();
} else if (perLanguage.id !== null) {
await _updatePerLanguage();
}
if (props.sentences.length !== 0 && perLanguage.id) {
await _iterateSentences();
}
await _saveRulesArticle();
};
If a perLanguage object doesn't exist, I create one in the database, and set it in state as such:
const _createPerLanguage = async () => {
const body = {
published: perLanguage.published,
premium: perLanguage.premium,
article: props.article.id,
language: props.lang_id,
calculated_skill: perLanguage.calculated_skill,
display_skill: perLanguage.display_skill,
};
try {
const response = await api.post("perLanguageCreateAPI", {
body: body,
});
await setPerLanguage(response.data);
} catch (e) {
console.log(e.response);
}
};
_saveRulesArticle above looks like this:
const _saveRulesArticle = async () => {
const newRules = props.rules.map((rule) => {
let ruleobj = {};
ruleobj["rule"] = rule;
ruleobj["per_language"] = perLanguage.id;
return ruleobj;
});
try {
const response = await api.post("ruleMappingCreateAPI", {
body: newRules,
});
} catch (e) {
console.log(e.response);
return;
}
};
However, because it's all within the same top function, _saveRulesArticle doesn't get access to the new perLanguage variable, it isn't updated, even though _createPerLanguage supposedly creates it and sets it.
I suspect there's some relation to this stack overflow page:
useState set method not reflecting change immediately
Most particularly the highest upvoted answer. I understand how that works for useEffect, but how would it work here? How do I update state inside a function, and then later inside that function, access the same updated state? Is this possible? Is this an anti-pattern?

React useSelector Value Not Changed Inside Async Function

I want to use the useSelector state to send the new bugs state to a server inside an async function, but the value does not change. What am I doing wrong?
When submitting a form I want to update the bugs state and send it to the server
Inside an async function I do dispatch(updateBugs(newBug)) and the state is updated so this works
I get the state with const { bugs } = useSelector((state) => state.bugs); and the state seems to be updated
When I send the updated bugs list with await sendUpdatedBugsToServer(bugs); inside the async function, the bugs state seems to be the old one.
■bug-actions.js
export const sendUpdatedBugsToServer = (newBugsList) => {
const storeData = async (newBugsList) => {
const response = await fetch(`${databaseURL}/bugs.json`, {
method: 'PUT',
body: JSON.stringify(newBugsList),
headers: { 'Content-Type': 'application/json' },
});
if (!response.ok) {
throw new Error('cannot store new bug');
}
};
try {
storeData(newBugsList);
} catch (error) {
console.error(error.message);
}
};
■UpdateBugs.js
const EditBug = () => {
const dispatch = useDispatch();
const { bugs } = useSelector((state) => state.bugs); //new bug state reflected here
const submitUpdatedBugs = async () => {
const newBug = {
title: enteredTitle,
details: enteredDetails,
steps: enteredSteps,
version: enteredVersion,
priority: enteredPriority,
assigned: enteredAssigned,
creator: enteredCreator,
id: enteredId,
};
await dispatch(updateBugs(newBug)); //update bugs state
await sendUpdatedBugsToServer(bugs); //new bug state not reflected here
}
};
const submitUpdatedBugHandler = (e) => {
e.preventDefault();
submitUpdatedBugs();
};

Why can't I access this variable from the state VUEX 4

I of course tried it with out the state.groupCrud.group and still no go. Is my syntax correct. I am using vuejs3 i will provide some screenshots of the object.
This is the State Object:
const state = () => ({
group: {}, //This is the one i am trying to access.
groups: [],
loading: false,
error: null,
success: false,
});
I am getting the data from api like this:
async getGroup({ commit }, id) {
try {
await commit('axiosSingleDataBegin');
const query = await DataService.get(`/groups/unique/${id}`);
await commit('axiosSingleDataSuccess', query.data.data.group);
} catch (err) {
await commit('axiosSingleDataErr', err);
}
},
And I am setting it to the state like this:
axiosSingleDataSuccess(state, data) {
state.loading = false;
state.group = data;
},
This is how i am using the state
setup() {
const { state, dispatch } = useStore();
const group = state.groupCrud.group;
const { params } = useRoute();
onMounted(() => {
dispatch('getGroup', params.id);
console.log(group); //doesnt work
});
// ...
},
This is the console.log(state.groupCrud); Object
This is the console.log(state.groupCrud.group) Object
I am getting a empty Proxy object when i try to use the state.groupCrud.group although the object is not empty

How do you pass a react component's props down to options after apollo-client mutation?

How do you pass a react component's props down to options after apollo-client mutation?
I am using react with apollo-client. In a component I am trying to run a delete mutation after which I want to remove the item from the local store without doing a refetchQueries. In order to do so I've been using the options.update command.
In order to update the store, I need the parent ID of the object I'm trying to delete. It's available in the react component, I just need to find a way to pass it down to the options.update function.
const { fundId } = this.props;
const variables = { documentId: document.id };
const options = { variables }
this.props.deleteFundDocument(options)
.then( response => console.log("Document successfully deleted", response) )
.catch( e => console.log("Document not deleted", e) )
export default graphql(FundDocumentQL.deleteFundDocument, {name: 'deleteFundDocument', options: FundDocumentQLOptions.deleteFundDocument})
)(DocumentDisplay)
Here's what I pass in to the options from FundDocumentQLOptions as you can see I get the fundId from localStorage which is kind of hacky. I'd rather try and pass it down properly.
const deleteFundDocument = {
update: (proxy, {data: {deleteFundDocument}}) => {
try {
if (localStorage.getItem('documentViewerFundId')) {
const fundId = localStorage.getItem('documentViewerFundId');
let data = proxy.readQuery({query: FundDocumentQL.allFundDocuments, variables: {fundId: fundId}});
console.log('data.allFundDocuments 1', data.allFundDocuments);
// console.log('documentId', documentId);
console.log('variables.documentId', variables.documentId);
const newDocuments = data.allFundDocuments.filter( item => {
return item.id !== deleteFundDocument.id;
});
console.log('newDocuments', newDocuments);
data.allFundDocuments = [...newDocuments];
console.log('data.allFundDocuments 2', data.allFundDocuments);
proxy.writeQuery({query: FundDocumentQL.allFundDocuments, data, variables: {fundId: fundId}});
}
} catch (e) {
console.log(e);
}
}
};
I saw this example in the apollo-client docs:
https://www.apollographql.com/docs/react/basics/mutations.html#graphql-mutation-options-variables
export default graphql(gql`
mutation ($foo: String!, $bar: String!) {
...
}
`, {
options: (props) => ({
variables: {
foo: props.foo,
bar: props.bar,
},
}),
})(MyComponent);
And I saw this answer:
Apollo can't access queryVariables in update: after a mutation
Reading the other answer here Apollo can't access queryVariables in update: after a mutation
I realized I could pass fundId from this.props into the update function when I created the options object ahead of the mutation.
const { fundId } = this.props;
const variables = { documentId: document.id };
const options = {
variables: variables,
update: (proxy, { data: { deleteFundDocument } }) => FundDocumentQLOptions.deleteFundDocument(proxy, deleteFundDocument, fundId)}
this.props.deleteFundDocument(options)
.then( response => console.log('Document successfully deleted', response) )
.catch( e => console.log('Document not deleted', e) )
export default graphql(FundDocumentQL.deleteFundDocument, {name: 'deleteFundDocument'})(DocumentDisplay)
From FundDocumentQLOptions
const deleteFundDocument = (proxy, deleteFundDocument, fundId) => {
try {
let data = proxy.readQuery({query: FundDocumentQL.allFundDocuments, variables: {fundId: fundId}});
// console.log('data.allFundDocuments 1', data.allFundDocuments);
data.allFundDocuments = data.allFundDocuments.filter( item => {
return item.id !== deleteFundDocument.id;
});
// console.log('data.allFundDocuments 2', data.allFundDocuments);
proxy.writeQuery({query: FundDocumentQL.allFundDocuments, data, variables: {fundId: fundId}});
} catch (e) {
console.log(e);
}
};

Categories

Resources