Here the addToCart function. i want to call this funtion and navigate to another page.
addToCart = () => {
const {product, quantity, variation, meta_data} = this.state;
const {dispatch} = this.props;
let check = true;
// Check select variations
if (product.get('type') === productType.VARIABLE) {
const attributeProduct = product
.get('attributes')
.filter(attr => attr.get('variation'));
if (!meta_data.size || attributeProduct.size !== meta_data.size) {
check = false;
showMessage({
message: 'Please select variations',
type: 'danger',
});
}
}
if (check) {
dispatch(
addToCart(
{
product_id: product.get('id'),
quantity,
variation,
product,
meta_data,
},
() => this.setState({isAddToCart: true}),
),
);
}
};
And Render function
<FooterProduct
isAddToCart={isAddToCart}
onPressAddCart={this.addToCart}
onPressBuyNow={
this.addToCart // function one
() => navigation.navigate(homeTabs.cart) // function two
}
/>
how can I run both? actually I try to create a buy now button.
thank you.
Create a custom method that calls both the methods like below
const combinedMethod = () => {
this.addToCart();
navigation.navigate(homeTabs.cart);
}
And use the above method like
<FooterProduct
isAddToCart={isAddToCart}
onPressAddCart={this.addToCart}
onPressBuyNow={combinedMethod}
/>
Try this one:
onPressBuyNow = () => {
this.addToCart(); // function one
navigation.navigate(homeTabs.cart); // function two
}
The answer would be either this or create a wrapper function like other folks suggest.
Edit
Modified the answer after Michael Mishin's comment.
Related
How can I get a list of cars for a customer
clients:
w21rffa3:
name: Johny
phone: 123123
cars:
fn1jnr12:
brand: AUDi
model: a6
number: 24f1
dsdasgf122:
brand: AUDi
model: a3
number: 62s14
My code
const ref = firestore().collection('clients');
const [clientsList, setClientsList] = useState([]);
useEffect(() => {
return ref.onSnapshot(clientsSnapshot => {
const clients = [];
const cars = [];
clientsSnapshot.forEach(client => {
const carsRef = ref.doc(client.id).collection('cars').onSnapshot(carsSnapshot => {
carsSnapshot.forEach(car => {
if (car.data().brand.length > 0) {
const {
brand,
model,
number
} = car.data();
cars.push({
id: car.id,
brand,
model,
number,
});
}
});
//Good result`
console.log('After forEach: ', cars);
});
//Bad result
console.log('After snapshot: ', cars);
const {
name,
phone
} = client.data();
clients.push({
id: client.id,
name,
phone,
cars: cars,
});
});
setClientsList(clients);
});
}, []);
cars list for customers
The error you facing is due to misuse/misunderstanding of how async/callback-based functions works. As I said in my comment - good result and bad result - bad result scripts are executed before good result due to onSnapshot is async, and you pass a callback function to it, which will be executed when data is available from firebase, so a bit "later" than the rest of the code.
Now about what can be done. The code is a bit tricky and I didnt really test it, so if anything - please, let me know.
const [clientsList, setClientsList] = useState([]);
useEffect(() => {
let carsUnsubscribeFns = [];
const clientUnsubscribeFn = ref.onSnapshot((clientsSnapshot) => {
// Reset everything and stop previously created listeners for Cars
setClientsList([]);
carsUnsubscribeFns.forEach((x) => x());
carsUnsubscribeFns = [];
clientsSnapshot.forEach((c) => {
const { name, phone } = c.data();
const client = { id: c.id, name, phone };
// In case you dont want to use optional chaining,
// remove the const client = ... line above
// and uncomment the line below
// but optional chaining is prefered anyway
// const client = { id: c.id, name, phone, cars: [] };
const carsUnsubscribeFn = ref
.doc(client.id)
.collection("cars")
.onSnapshot((carsSnapshot) => {
// Mutate the Client object directly
client.cars = carsSnapshot.docs
.map((x) => ({ id: x.id, ...x.data() }))
.filter((x) => x.brand?.length > 0);
// mark ClientsList as updated to force a rerender
// due to we mutated one of the entities inside
setClientsList((curr) => [...curr]);
});
carsUnsubscribeFns.push(carsUnsubscribeFn);
setClientsList((curr) => {
curr.push(client);
return [...curr];
});
});
// clean-up function returned from hook to stop all the listeners
return () => {
[clientUnsubscribeFn, ...carsUnsubscribeFns].forEach((x) => x());
};
});
}, []);
I am trying to pass a key for navigation, which specifies to show the query/page after the current query call.
useform.ts
...
...
export const useupdateSurveyForm = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: updateSurveyForm,
onSuccess: (data) => {
queryClient.invalidateQueries(["searched-public-survey"]);
},
});
};
here added "invalidateQueries(["searched-public-survey"]" directly then the code is working properly, but I want to make this dynamic. like,
queryClient.invalidateQueries(navigationqueryKey);
For that I made some changes
plans.ts
...
...
const {
mutate: updateArchiveSurveyStatus,
navigationqueryKey: "searched-public-survey",
} = useupdateSurveyForm();
...
...
pass "navigationKey: "searched-public-survey", but it shows an error
Property 'searched-public-survey' does not exist on type 'UseMutationResult<any, unknown, SurveyUpdatePayload, unknown>'.
Give me some solution to fix this problem.
I dont know if it is correct to pass the value for the query that way.
The statement from the plain.ts is just the return value. I did not found anything in the docs which would lead to putting in the navigation query key.
If I get you correctly I think what you want to do would look like:
export const useupdateSurveyForm = (key: string) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: updateSurveyForm,
onSuccess: (data) => {
queryClient.invalidateQueries([key]);
},
});
};
And the plans.ts would then look like:
const {
mutate: updateArchiveSurveyStatus,
} = useupdateSurveyForm("searched-public-survey");
Maybe that helps. :-)
I have a piece of code which updates user settings when a number input box is called in react-redux. The first portion of the code works fine: The "onChange" function gets called. But now it gets weird. onChange is called twice and the code jumps through a bunch of the react back end, touches the action creator then execution skips the entire function and exits at the closing brace.
I have many other Redux functions created using the same model that work perfectly and cannot understand why this one is not being called.
Here is my code:
mapDispatchToProps
const mapDispatchToProps = (dispatch) => {
return {
SMSAdmin_Get_Users: () => { return dispatch(SMSAdmin_Get_Users()) },
SMSAdmin_Load_User: (userId, userName, oldData = null, startVal = 0, number = 20) =>
{
return dispatch(SMSAdmin_Load_User(userId, userName, oldData, startVal, number))
},
SMSAdmin_Update_User: (user, province, credits) => { return
SMSAdmin_Update_User(user, province, credits)
},
SMSAdmin_setCurrentUpload: (userName) => { return SMSAdmin_setCurrentUpload(userName) }
};
}
Calling Input
<Form.Control type="number"
style={{ width: '100px' }}
defaultValue={this.props.SMSAdmin.user.credits}
id='numCredits'
onChange={(e) => this.updateUser(e.target)}
/>
I know that in the input I don't need to pass in the event but included it should I need it in the future for some purpose.
onChange function
//this gets called twice when making a single change in the input box
updateUser = () => {
var province = document.getElementById("provinceId");
var credits = document.getElementById("numCredits");
var user = document.getElementById("lblUser");
if (user && user.value !== '') { //safeguard to avoid trying to update nothing
//execution hits here once, then after the second hit proceeds into Redux code
this.props.SMSAdmin_Update_User(user.value, province.value, credits.value);
}
}
Redux action creator
// Execution touches here
export const SMSAdmin_Update_User = (user, province, credits) => (dispatch) => {
//then here jumps to bottom
dispatch(Actions.SMSAdmin_User_Updating());
var data = { 'mode': 'UPDATE', 'user': user, 'province': province, 'credits': credits }
var init = fetchInit();//copy to not modify the original
init.method = "POST";
init.body = JSON.stringify(data);
var myReq = new Request('/dataAPI/SMS', init);
return fetch(myReq)
.then((response) => {
if (response.ok) {
return response;
}
else {
var error = new Error("Error " + response.statusText);
error.response = response;
throw error;
}
}, (error) => {
var err = new Error(error.message);
throw err;
})
.then((response) => { return response.json() })
.then((resp) => {
handleData(dispatch, Actions.SMSAdmin_User_Updated, resp)
})
.catch((err) => {
var msg = err.message;
return dispatch(Actions.SMS_Send_Failed(msg));
});
} //touches here and exits
I think that this is all the code involved. If I am missing anything let me know and I will include it. I am baffled how execution touches the function but does not execute it, nor does Chrome debug break at a breakpoint set on the function header.
The issue is that action is not dispatched properly. dispatch is not attached to SMSAdmin_Update_User function.
Inside mapDispatchToProps, update the following:
SMSAdmin_Update_User: (user, province, credits) => {
// Add dispatch here. It is already done for other functions such as SMSAdmin_Load_User
return dispatch(SMSAdmin_Update_User(user, province, credits))
},
I was using this test when I had a bug, so I used the trim function for resolve it, and the these test fail, tried in different ways but didn't found the solution
const generalWrapper = shallow(<AddVehiclesTable {...generalProps} />)
const generalInstance = generalWrapper.instance()
describe('onSearchChange', () => {
test('should change the "search" state', () => {
const theFilterValue = 'a new filter value'
generalWrapper.find('.filter-input').simulate('change', { target: { value: theFilterValue } })
const expectedState = Object.assign({}, generalInstance.state)
expectedState.searchValue = { 'target': { 'value': theFilterValue } }
expect(generalInstance.state).toEqual(expectedState)
expect(generalInstance.state.userInteractedWithComponent).toBe(true)
})
})
onSearchChange (searchValue) {
const value = searchValue.trim()
this.setState({ searchValue: value, userInteractedWithComponent: true })
}
Error message
TypeError: searchValue.trim is not a function
Any suggestions
Your function gets the Object as a parameter.
Expose field that you needed
I don't see the whole picture, but can guess that you need something like
onSearchChange ({ target: { value: incomeValue } }) {
const value = incomeValue.trim()
this.setState({ searchValue: value, userInteractedWithComponent: true })
}
code is like this:
componentDidMount() {
this.setState(({getPublicTodosLength}, props) => ({
getPublicTodosLength: () => this.getPublicTodosLengthForPagination() // no returned value
}));
}
getPublicTodosLengthForPagination = async () => { // get publicTodos length since we cannot get it declared on createPaginationContainer
const getPublicTodosLengthQueryText = `
query TodoListHomeQuery {# filename+Query
viewer {
publicTodos {
edges {
node {
id
}
}
}
}
}`
const getPublicTodosLengthQuery = { text: getPublicTodosLengthQueryText }
const result = await this.props.relay.environment._network.fetch(getPublicTodosLengthQuery, {})
return result.data.viewer.publicTodos.edges.length;
}
getPublicTodosLengthForPagination is not invoked and the returned value is not assigned.Also, When i invoke it right away e.g. without () => it's assigned value is a promise? I am expecting int/number, the return value of edges.length. help?
The returned value is not assigned because you are not invoking the function rather assigning it.
componentDidMount() {
this.setState(({getPublicTodosLength}, props) => ({
getPublicTodosLength: this.getPublicTodosLengthForPagination()
}));
}
I'm not sure why you're setting state like that, maybe you could help explain what you're doing. In the meantime shouldn't it be written like this:
componentDidMount() {
this.setState({
getPublicTodosLength: await this.getPublicTodosLengthForPagination() // no returned value
});
}
getPublicTodosLengthForPagination = async () => { // get publicTodos length since we cannot get it declared on createPaginationContainer
const getPublicTodosLengthQueryText = `
query TodoListHomeQuery {# filename+Query
viewer {
publicTodos {
edges {
node {
id
}
}
}
}
}`
const getPublicTodosLengthQuery = { text: getPublicTodosLengthQueryText }
const result = await this.props.relay.environment._network.fetch(getPublicTodosLengthQuery, {})
return result.data.viewer.publicTodos.edges.length;
}