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();
};
Related
I have 4 functions, for 1st three functions, I can send the data in provide. For 4th function(
getViewApplicationDetails
), I am trying to fetch api and get application name, now I want that in mounted because, I want the application name as soon as component is rendered so I am trying to execute it in mounted but when I call the it, it's giving me error. Initially application name is empty and it should have the current application name when I fetch the api, the same application name will be used in provide and then I can use that in inject and then in any other component.
import { computed, inject, onMounted, provide, reactive } from "vue";
export const initStore = () => {
onMounted(()=>{
this.getViewApplicationDetails()
});
// State
const state = reactive({
name: "Bob Day",
email: "bob#martianmovers.com",
applicationName: "",
breadcrumbsData: [
{
name: "Home",
text: 'Home',
disabled: false,
href: '/'
}
]
});
// Getters
const getUsername = computed(() => state.name);
const getEmail = computed(() => console.log("state.email",state.email));
const getBreadcrumbsData=computed(()=>state.breadcrumbsData)
console.log("state.applicationName",state.applicationName)
//this is the temporary function
const getApplicationName=computed(()=>state.applicationName)
const getViewApplicationDetails=computed(()=> {
var viewApplicationDetailsParams = {
applicationId: this.$route.query.applicationId,
applicationStatus:this.$route.query.appStatus,
authType: "api",
clientId: process.env.VUE_APP_EXTERNAL_API_CLIENT_ID,
clientSecret: process.env.VUE_APP_EXTERNAL_API_CLIENT_SECRET
};
axios({
method: "post",
url: process.env.VUE_APP_BLUJ_BACKEND_URL + "/viewapplicationDefinition",
data: viewApplicationDetailsParams,
headers: {
"content-type": "application/json",
},
})
.then((response) =>{
this.viewDefinitionResponse = response.data.Definitions;
let applicationName = viewDefinitionResponse.application_display_name.en;
console.log("tyfgyhkjlfhgjklnm",applicationName)
setApplicationName(applicationName)
})
.catch((error) => {
console.log("error", error);
});
});
getViewApplicationDetails()
// Mutations
const setUsername = (name) => {
state.name = name;
};
const setEmail = (email) => {
state.email = email;
};
const setBreadCrumbsData=(breadcrumbsData)=>{
state.breadcrumbsData=breadcrumbsData;
}
const setApplicationName=(appName)=>{
state.applicationName=appName
}
// Actions
const updateUsername = (name) => {
setUsername(name);
};
const updateEmail = (email) => {
setEmail(email);
};
provide("getUsername", getUsername);
provide("getEmail", getEmail);
provide("updateUsername", updateUsername);
provide("updateEmail", updateEmail);
provide("getViewApplicationDetails", getViewApplicationDetails);
provide("getApplicationName", getApplicationName);
provide("getBreadcrumbsData", getBreadcrumbsData);
};
export const useStore = () => ({
getUsername: inject("getUsername"),
getEmail: inject("getEmail"),
updateUsername: inject("updateUsername"),
updateEmail: inject("updateEmail"),
viewApplicationDetails: inject("getViewApplicationDetails"),
getBreadcrumbsData: inject("getBreadcrumbsData"),
getApplicationName: inject("getApplicationName")
});
This is the code snippet.
const getUsername = computed(() => state.name);
const getEmail = computed(() => console.log("state.email",state.email));
const getBreadcrumbsData=computed(()=>state.breadcrumbsData)
I am getting data for this, but for getViewApplicationDetails, it's not working. While hovering over rest of the functions, it is showing "const getUsername: ComputedRef", like this. But, for getViewApplicationDetails, it shows "const getViewApplicationDetails: ComputedRef", this. I think it is not taking it as function or something. Error image is in the link.enter image description here
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.
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
I am trying to pre-fetch data using react-query prefetchQuery. When I am inspecting browser DevTools network tab I can see that data that was requested for prefetchQuery is coming from the back-end but for some reason when I look into react-query DevTools it does generate the key in the cache but for some reason the Data is not there. Let me know what I am doing wrong.
import { useState, useEffect } from 'react';
import { useQuery, useQueryClient } from 'react-query';
import axios from 'axios';
const baseURL = process.env.api;
async function getSubCategoryListByCategoryId(id) {
// await new Promise((resolve) => setTimeout(resolve, 300));
console.log(`${baseURL}/category/subcategories/${id}`);
try {
const { data } = await axios.request({
baseURL,
url: `/category/subcategories/${id}`,
method: 'get',
});
console.log('data getSubCategoryListByCategoryId index: ', data);
return data;
} catch (error) {
console.log('getSubCategoryListByCategoryId error:', error);
}
}
// const initialState = {
// };
const ProductCreate = () => {
const [values, setValues] = useState(initialState);
const queryClient = useQueryClient();
const { data, isLoading, isError, error, isFetching } = useQuery(
'categoryList',
getPosts
);
const dataList = JSON.parse(data);
useEffect(() => {
setValues({ ...values, categories: dataList });
dataList.map((item) => {
console.log('useEffect values.categories item.id: ', item._id);
queryClient.prefetchQuery(
['subCategoryListByCategoryId', item._id],
getSubCategoryListByCategoryId(item._id)
);
});
}, []);
return <h1>Hello</h1>;
};
export default ProductCreate;
The second parameter to prefetchQuery expects a function that will fetch the data, similar to the queryFn passed to useQuery.
But here, you are invoking the function, thus passing the result of it into prefetchQuery:
getSubCategoryListByCategoryId(item._id)
if you want to do that, you can manually prime the query via queryClient.setQueryData, which accepts a key and the data for that key passed to it.
otherwise, the fix is probably just:
() => getSubCategoryListByCategoryId(item._id)
So I'm trying out basic todo app with edit and delete feature. I'm having problems with my edit feature. I have two main components in my app namely InputTodo for adding todo items and ListTodo which contains two additional subcomponents (TodoItem for each todo and EditTodo which shows an editor for a selected todo). Whenever the Edit Button inside a certain TodoItem is clicked, the EditTodo component is showed. When the Confirm button in EditTodo component is clicked, a PUT request will be sent to update the database (PostgreSQL in this case) through Node. After successfully sending this send request, I would like to re-render the list of TodoItem components. I'm doing this by fetching the updated list of values from the database through a different GET request then calling setState given the response from the GET request. However, the GET request's response doesn't reflect the PUT request done earlier. Thus, the app still renders the un-updated list of todos from the database.
Here are some code snippets
const ListTodo = (props) => {
const [todos, setTodos] = useState([]);
const [editorOpen, setEditorOpen] = useState(false);
const [selectedId, setSelectedId] = useState();
const getTodos = async () => {
console.log('getTodos() called');
try {
const response = await fetch("http://localhost:5000/todos");
const jsonData = await response.json();
setTodos(jsonData);
console.log(todos);
} catch (err) {
console.error(err.message);
}
console.log('getTodos() finished');
};
const editTodo = async description_string => {
console.log('editTodo() called');
try {
const body = { description: description_string };
const response = await fetch(
`http://localhost:5000/todos/${selectedId}`,
{
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body)
}
);
console.log(response);
await getTodos();
props.handleListModified();
} catch (err) {
console.error(err.message);
}
console.log('editTodo() finised');
}
const handleItemButtonClick = (button, row_key) => {
if (button === 'delete') {
deleteTodo(row_key);
setEditorOpen(false);
} else if (button === 'edit') {
setEditorOpen(true);
setSelectedId(row_key);
console.log(todos.filter(todo => { return todo.todo_id === row_key})[0].description);
}
};
const handleEditorButtonClick = async (button, description_string) => {
if (button === 'cancel') {
setSelectedId(null);
} else if (button === 'confirm') {
await editTodo(description_string);
}
setEditorOpen(false);
};
useEffect(() => {
console.log('ListTodo useEffect() trigerred');
getTodos();
}, [props.listModified]);
return(
<Fragment>
<table>
<tbody>
{todos.map( todo => (
<TodoItem
key={todo.todo_id}
todo_id={todo.todo_id}
description={todo.description}
handleClick={handleItemButtonClick} />
))}
</tbody>
</table>
{ editorOpen &&
<EditTodo
handleEditorButtonClick={handleEditorButtonClick}
description={todos.filter(todo => { return todo.todo_id === selectedId})[0].description}
selectedId={selectedId} /> }
</Fragment>
);
};
I guess that the problem is - In editTodo function, you are calling getTodos() function. But, you are not updating the state with the response you get. See if this helps.
const response = await fetch(
`http://localhost:5000/todos/${selectedId}`,
{
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body)
}
);
console.log(response);
setTodo(await getTodos()); // Update the state with the values from fetch