At first the state[options] accepts and saves the payload properly but after a refresh it recieves the action but gives an error of state.options.concat is not a function.
code for options state:
reducers:{
addOptions:(state,action)=>{
let value = action.payload;
console.log(value); //<--- i am receiving a string
state.options= state.options.concat(value);
localStorage.setItem("options",JSON.stringify(state));
},
calling function-->
const handleClick = (e)=>{
let value =e.target.innerHTML;
dispatch(addOptions(value));
}
i think there is no problem with this function cause it worked properly on first render and after refresh it
send the data properly
Please help me on this one i've been banging my head on this bug for a long time
ThankYou in Advance
addOptions recieves the action.payload but .concat is giving me problem on refresh
Related
I'm using Inertia.js and I've been loving it.
I'm having a problem anyway that I cant seem to figure out. I have a select input that will contain options from the database but a lot of them aprox. 30/40k so my idea is to just take the first 20 and then let the user input a search and bring the first 20 that match that result.
All my backend is working ok but the problem I'm having is displaying the updated select options after search.
The relevant code is the following: First the call to AsyncSelect Component from the react-select package. This components needs a loadOptions property that will call a function when the user start typing
<AsyncSelect
name="proveedores"
id="proveedores"
defaultOptions={proveedores}
loadOptions={handleChange}
/>
The function that gets call is this, it recieves the input value and a callback, within this callback I'm supposed to search for the new data and return it
function handleChange(inputValue,callback) {
setValues(values => ({
...values,
["search"]: inputValue
}));
callback()
}
The problem is that to load the new data on search I'm using useEffect
useEffect(() => {
if (prevValues) {
const query = pickBy(values)
Inertia.get(window.location.href, query, {
replace: true,
preserveState: true
});
}
}, [values]);
The search with useEffect works ok, if I do a console.log I will see the list of proveedores updated but the problem is how do I tell the callback from handleChange function that it should listen for useEffect and on finish use the new value of proveedores
If anyone had to do something like this (React Select with search data from database) using Inertia + React, i would really appreciate some feedback on how to achieve it.
Thanks!!
I got simple blog with arficles, and when user click edit button he got form filled with articles data - title, description, body and tags. I use useEffect to get data and fill form, when I got "id". If there is no "id" form should be blank. here is my useEffect:
useEffect(() => {
if (id) {
isLoading = true;
return props.onLoad(userService.articles.get(id));
}
props.onLoad(null);
}, [id]
);
but when I reload page id not changed, and func userService.articles.get(id) not run, and all datas gone. I need advice how to fix it? may be I need to use other deps for useEffect, but now I have no idea what deps i can use exept id.
upd:
thank you all for help. all i want is:
when the edit page load/reload and "id" exist -> fills form fields
when "id" not exist -> blank form fields
now when I reload edit page i got id - but all datas gone, and i got blank form :(
Here is the full code: codesandbox
p.s. i use free API - so you can create user in a sec with any imagined email, username and password. you don't need mail confirmation.
You should use this.props.match.params to access your id that comes from the url.
useEffect(() => {
if (props.match.params.id) {
setIsloading(true);
userService.articles.get(props.match.params.id)
.then((resp) => {
setIsloading(false);
props.onLoad(resp)
})
} else {
props.onLoad(null);
}
}, [props.match.params.id]);
Also you should rely on useState to manage your isLoading variable.
const [isLoading, setIsloading] = useState(false);
I did a bit more digging into the code you have provided.
The initialValues will be first empty because the data coming from the props is not there yet. And once the initialValues have been set you can't change them dynamically, you have to resort to the antd Form api.
You cannot set value for each form control via value or defaultValue
prop, you should set default value with initialValues of Form. Note that initialValues cannot be updated by setState dynamically, you
should use setFieldsValue in that situation.
The key here is to use another useEffect with dependencies to your form values comming from the props and use those to reset the form values via setFieldsValue.
try to useEffect without options and it will run just when the page loads for the first time
useEffect(() => {
if (id) {
isLoading = true;
return props.onLoad(userService.articles.get(id));
}
props.onLoad(null);
}, []
);
Based on the assumption that you want props.onLoad to run whenever there is a defined "id" or the defined "id" changes:
Returning a function from a useEffect hook (as you do with return props.onLoad(...)) is specifically for "cleaning up" things like side effects or subscriptions. A function returned inside a useEffect hook will only run when the component unmounts. See docs here. Also it doesn't seem like you are even passing a function to run on cleanup. You're passing the result of props.onLoad to run on cleanup, which based on the function name doesn't seem like it is intended to return another function.
So, if you want props.onLoad() to run if the "id" is defined, remove the return before props.onLoad. That return is telling React to hold (what it thinks is a function) for cleanup on unmount. If it's still not working, I think we'll need more information on what exactly props.onLoad is doing.
I am using react native navigation and have two tabs. One of them has a list of entites, the other has a form to submit entities. When ever a new entity is submitted, I'd like to refresh the first tab to be sure, the newest data gets loaded.
I navigate to the first tab like this:
navigation?.navigate('Main', {refresh: true});
This props gets saved as follows:
let {refresh} = route.params;
To check, if the screen needs to refresh, I added a listener in useEffect() like this:
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () =>{
if(refresh){
doRefresh()
}
})
}, [])
Unfortunately, neither "refresh" nor "route.params" directly is ever true inside the listener. Passing the param works, because I took a closer look at the var and it gets true, whenever I submit.
Do I need to access the route.params inside a navigation listener in another way?
Thanks and hit me up, if you need more information on this
The issue is that your useEffect only runs once as your dependencies array [] is empty, and therefore your listener only receives the initial value of refresh.
You need to pass refresh as a dependency to useEffect, and I don't think you even need the focus listener in your case so you would end up with this:
useEffect(() => {
if (refresh) {
doRefresh()
}
}, [refresh])
const onPressCountry = (item,index) => {
navigation.push('SignUp2', {selectedCountryId:item?.countryID, selectedCountryName: item?.name} )
}
use navigation.push instead of navigation.navigate
I sometimes get a race condition when trying to use onSubscription hook from #apollo/react-hooks package in the following way.
let { data, loading, error } = useSubscription(MY_SUBSCRIPTION)
if (loading) return 'Loading...';
if (error) return 'Error...';
...
When I load the page, most of the time data gets filled perfectly and eventually loading will turn false, but every ~5th try there's some kind of race condition where loading stays true forever and data is undefined.
GraphQL query:
export const EXERCISE_SUBSCRIPTION = gql`
subscription {
exercises {
id
title
tasks {
id
title
start_time
end_time
}
}
}
`;
Package version is the (currently) latest:
#apollo/react-hooks": "^3.1.0-beta.0", but I have also tried with previous versions.
Has anyone experienced something similar and know how to solve it?
If you run into this issue, I found a workaround hack. You can see that when I add the callback option onSubscriptionData, the data IS present in there, but somehow does not end up in the data object outside.
// <HACK>
// sometimes data object is empty, but onSubscriptionData is filled.
// in that case use data from onSubscriptionData method.
const [dataFromCb, setDataFromCb ] = useState(null)
let { data, loading } = useSubscription(INJECT_SUBSCRIPTION, {
onSubscriptionData: (res) => {
setDataFromCb(res.subscriptionData.data)
},
});
if (loading && !dataFromCb) return 'Loading...';
data = (data === undefined) ? dataFromCb : data;
// </HACK>
Ok, I do believe I found the answer to this one, but to verify, you may need to double check and/or post your query code. Apparently Apollo is trying to marry up the data as it arrives, and it uses the id fields to do that by default. I had a query that was missing those ids in some nested layers of my structure, and when I put them in, this error has disappeared. It wasn't until I ran into this error that I found the resources that pointed me in the right direction.
For reference: https://github.com/apollographql/react-apollo/issues/1003
I had the same issue with useSubscription loading stuck. Afterwards noticed that I kept this hook in the child component, so moved it on the same level (parent component) with the useQuery which triggered subscriptions on the server. So in my case it was React rendering issue which affected such a behaviour.
I'm creating a webshop for a hobby project in Nuxt 2.5. In the Vuex store I have a module with a state "currentCart". In here I store an object with an ID and an array of products. I get the cart from the backend with an ID, which is stored in a cookie (with js-cookie).
I use nuxtServerInit to get the cart from the backend. Then I store it in the state. Then in the component, I try to get the state and display the number of articles in the cart, if the cart is null, I display "0". This gives weird results. Half of the time it says correctly how many products there are, but the Vuex dev tools tells me the cart is null. The other half of the time it displays "0".
At first I had a middleware which fired an action in the store which set the cart. This didn't work consistently at all. Then I tried to set the store with nuxtServerInit, which actually worked right. Apparently I changed something, because today it gives the descibed problem. I can't find out why it produces this problem.
The nuxtServerInit:
nuxtServerInit ({ commit }, { req }) {
let cartCookie;
// Check if there's a cookie available
if(req.headers.cookie) {
cartCookie = req.headers.cookie
.split(";")
.find(c => c.trim().startsWith("Cart="));
// Check if there's a cookie for the cart
if(cartCookie)
cartCookie = cartCookie.split("=");
else
cartCookie = null;
}
// Check if the cart cookie is set
if(cartCookie) {
// Check if the cart cookie isn't empty
if(cartCookie[1] != 'undefined') {
let cartId = cartCookie[1];
// Get the cart from the backend
this.$axios.get(`${api}/${cartId}`)
.then((response) => {
let cart = response.data;
// Set the cart in the state
commit("cart/setCart", cart);
});
}
}
else {
// Clear the cart in the state
commit("cart/clearCart");
}
},
The mutation:
setCart(state, cart) {
state.currentCart = cart;
}
The getter:
currentCart(state) {
return state.currentCart;
}
In cart.vue:
if(this.$store.getters['cart/currentCart'])
return this.$store.getters['cart/currentCart'].products.length;
else
return 0;
The state object:
const state = () => ({
currentCart: null,
});
I put console.logs everywhere, to check where it goes wrong. The nuxtServerInit works, the commit "cart/setCart" fires and has the right content. In the getter, most of the time I get a null. If I reload the page quickly after another reload, I get the right cart in the getter and the component got the right count. The Vue dev tool says the currentCart state is null, even if the component displays the data I expect.
I changed the state object to "currentCart: {}" and now it works most of the time, but every 3/4 reloads it returns an empty object. So apparently the getter fires before the state is set, while the state is set by nuxtServerInit. Is that right? If so, why is that and how do I change it?
What is it I fail to understand? I'm totally confused.
So, you know that moment you typed out the problem to ask on Stackoverflow and after submitting you got some new ideas to try out? This was one of them.
I edited the question to tell when I changed the state object to an empty object, it sometimes returned an empty object. Then it hit me, the getter is sometimes firing before the nuxtServerInit. In the documentation it states:
Note: Asynchronous nuxtServerInit actions must return a Promise or leverage async/await to allow the nuxt server to wait on them.
I changed nuxtServerInit to this:
async nuxtServerInit ({ commit }, { req }) {
...
await this.$axios.get(`${api}/${cartId}`)
.then((response) => {
...
}
await commit("cart/clearCart");
So now Nuxt can wait for the results. The Dev Tools still show an empty state, but I think that is a bug, since I can use the store state perfectly fine in the rest of the app.
Make the server wait for results
Above is the answer boiled down to a statement.
I had this same problem as #Maurits but slightly different parameters. I'm not using nuxtServerInit(), but Nuxt's fetch hook. In any case, the idea is essentially: You need to make the server wait for the data grab to finish.
Here's code for my context; I think it's helpful for those using the Nuxt fetch hook. For fun, I added computed and mounted to help illustrate the fetch hook does not go in methods.
FAILS:
(I got blank pages on browser refresh)
computed: {
/* some stuff */
},
async fetch() {
this.myDataGrab()
.then( () => {
console.log("Got the data!")
})
},
mounted() {
/* some stuff */
}
WORKS:
I forgot to add await in front of the func call! Now the server will wait for this before completing and sending the page.
async fetch() {
await this.myDataGrab()
.then( () => {
console.log("Got the messages!")
})
},