react native get response from then and assign to variable - reactjs

I am trying to get thumbnail path and storing to a variable to be used, But I am getting undefined
getThumbnail(filePath){
let thumbnailURL = RNThumbnail.get(filePath)
.then((response) => response.path)
.then((responseData) => {
console.warn(responseData);
return responseData;
}).catch(error => console.warn(error));
alert(thumbnailURL);
//return thumbnailURL;
}

.then doesn't work like that, it won't return a value. You could do:
let thumbnailURL;
RNThumbnail.get(filePath)
.then((response) => response.path)
.then((responseData) => {
thumbnailURL = responseData;
alert(thumbnailURL);
}).catch(error => console.warn(error));
but you have to continue computation inside the second then call because the value is only going to be reliable there
You're better off using async/await, just refactor your code to this:
async function getThumbnail(filePath){
try {
let thumbnailURL = await RNThumbnail.get(filePath)
alert(thumbnailURL)
} catch(err) {
console.warn(err)
}
read more about async / await

For React app, most likely you will want to set the response as state:
state = {
thumbnailURL: ''
}
getThumbnail = (filePath) => {
RNThumbnail.get(filePath)
.then(response => response.path)
.then(responseData => {
this.setState({
thumbnailURL: responseData
})
})
.catch(error => console.warn(error))
}
render() {
return (
<img src={this.state.thumbnailURL} />
)
}
You will need arrow function on getThumbnail for lexical binding so that you can access this.setState().
Edit:
You can't actually make getThumbnail() return thumbnailURL value right away. getThumbnail() can however return the promise, and you resolve it at the place where you want access to thumbnailURL:
getThumbnail = filePath => {
return RNThumbnail.get(filePath)
.then(response => response.path)
.then(responseData => responseData)
.catch(error => console.warn(error))
}
IWannaAccessThumbnailURLHere = () => {
this.getThumbnail('....')
.then(thumbnailURL => {
// do things with thumbnailURL
})
}
Or, use setState, re-render then you can access this.state.thumbnailURL in the next render-cycle.

Related

React Redux Axios Api Get call with path parameters

I am trying to do a axios get call to my backend server with path variable and save the response data to the store. Unfortunately it only works for the get call with no path variables. still I can also log the response in the console, but I am unable to dispatch the response.data to the store
fetchByCardNumber: (CardNumber) => axios.get(baseURL+'loyalty/loyaltyCustomer/card/'+ CardNumber)
export const fetchByCardNumber = (CardNumber) => dispatch => {
LoyaltyAPI().fetchByCardNumber(CardNumber)
.then(response => {
if (response.status !== 200){
dispatch(Customer(null))
} else {
dispatch(Customer(response.data))
}
}).catch(error => {
return error;
})
}
But wherever I have used the url without pathVaribale in axios get call it works.
Eg : fetchCards: () => axios.get(baseURL+'loyalty/loyaltyCard/all')
While using the above URL I can dispatch the response to the store and get it.
//use it like that without curly braces between {cardNumber}
fetchByCardNumber: (CardNumber) => axios.get(baseURL+'loyalty/loyaltyCustomer/card/'+ CardNumber)
export const fetchByCardNumber = (CardNumber) => dispatch => {
LoyaltyAPI().fetchByCardNumber(CardNumber)
.then(response => {
if (response.status !== 200){
dispatch(Customer(null))
} else {
dispatch(Customer(response.data))
}
}).catch(error => {
return error;
})
}
The issue was with the way on dispatching the response to the store. The below code worked.
export const fetchByCardNumber = (CardNumber) => dispatch => {
LoyaltyAPI().fetchByCardNumber(CardNumber)
.then(response => {
if (response.status !== 200){
store.dispatch(SelectedCustomer(null))
} else {
store.dispatch(SelectedCustomer(response.data))
}
}).catch(error => {
return error;
})
}

update state with data return undefined

I have one state called data that is empty object state={data:{}} I called RestAPI updated state USING set state when I console log it returned the data in the correct format but data that I need is this.state.data.title.rendered it says undefined but in console log it has data
Rest Api is like this:
{id:5,title:{rendered:"home is good"}}
fetch(`http://localhost/react-wordpress/wp-json/wp/v2/posts/${this.props.match.params.id}`)
.then((response) => response.json())
.then((responseJson) => {
const { title, fimg_url, content } = responseJson;
this.setState({ title, fimg_url, content });
this.setState({ data: responseJson })
})
.catch((error) => {
console.error(error);
});
In rendered method {this.state.data.title.rendered} return undefined while {this.state.title.rendered} return correct
Yes. Maybe it is undefined before fetching from backend.
So you need to validate if it is okay to render it like below:
const { data } = this.state;
return (
<div>
{ data && data.title && data.title.rendered
&& ( <h1>data.title.rendered</h1> )
}
<div>
);
try like this
fetch(`http://localhost/react-wordpress/wp-json/wp/v2/posts/${this.props.match.params.id}`)
.then((response) => response.json())
.then((responseJson) => {
const { title, fimg_url, content } = responseJson;
this.setState({ data: {title, fimg_url, content} });
})
.catch((error) => {
console.error(error);
});

Assigning return values from api to state in React

Hi I am trying to call an api assign the returned values to a state object in React, the API is returning values but the values are not being set to state, not understanding what's the reason thank you
handleDDLCommunityChange = event => {
let filesFromApi = []; // ["file1", "file2", "file3", "file4"];
fetch('https://localhost:44352/api/files/Community-1')
.then((response) => {
return response.json();
})
.then(data => {
filesFromApi = data.map(file => { return { value: file, display: file } });
}).catch(error => {
console.log(error);
debugger;
});
console.log(filesFromApi);
this.setState({
files: filesFromApi.map(file => {
return {
fileName: file,
checked: false
};
})
});
};
fetch is an async method. An async method dispatches an action with the callbacks and unblocks following code branch from executing. The callbacks are then used to act on completion (success or failure) of the async method execution.
As you are calling the setState outside of the callbacks of the fetch call's chain, it's not guaranteed to run after the fetch call is done. As Sudheer has pointed out in their comment, you should try to set the state in a then block of the fetch chain.
warning: untested code
handleDDLCommunityChange = event => {
let filesFromApi = []; // ["file1", "file2", "file3", "file4"];
fetch('https://localhost:44352/api/files/Community-1')
.then(response => response.json())
.then(data => {
filesFromApi = data.map(file => ({ value: file, display: file });
this.setState({
files: filesFromApi.map(file => ({
fileName: file,
checked: false
})
})
});
}).catch(error => {
console.log(error);
debugger;
});
};

Updating Data in Firebase using React

I am updating an object in firebase using React js.
I'm using this boilerplate as reference.
updateBookList: (id, data) => {
return firebaseDb.ref('NewBooks').child(id).update(data).then(() => {
return {};
}).catch(error => {
return {
errorCode: error.code,
errorMessage: error.message
}
});
},
The following updates the Books fine.
What I want to do is return the result instead of returning a blank {}. How can I return the result of what I updated?
This is how I fetch books:
fetchBooks: () => {
return new Promise((resolve, reject) => {
const bookSub = firebaseDb.ref('NewBooks').on("value", books => {
resolve(books.val());
}, error => {
reject(error);
})
})
},
If you want to return the value, you need to retrieve it. You can do that using once and the value event, which returns a promise that resolves to a Firebase snapshot:
updateBookList: (id, data) => {
let ref = firebaseDb.ref('NewBooks');
return ref
.child(id)
.update(data)
.then(() => ref.once('value'))
.then(snapshot => snapshot.val())
.catch(error => ({
errorCode: error.code,
errorMessage: error.message
}));
}
Also, you could simplify your fetchBooks by using once there, too:
fetchBooks: () => {
return firebaseDb.ref('NewBooks')
.once("value")
.then(snapshot => snapshot.val());
}
once returns a promise, so you don't have to create your own and you won't have a dangling event listener. The call to on in your implementation of fetchBooks will see a listener added with each call and multiple calls to resolve will be attempted if the database changes.

How can I return a promise from my ActionCreator in React Redux

I have the following handler that dispatches two actions...
_onPress = () => {
let { request,userId} = this.props;
this.props.dispatch(acceptRequest(request.id,userId))
this.props.dispatch(navigatePop());
}
What I would like this to look like instead is the following...
_onPress = () => {
let { request,userId} = this.props;
this.props.dispatch(acceptRequest(request.id,userId))
.then(this.props.dispatch(navigatePop()))
}
My ActionCreator looks like this...
export function acceptRequest(requestId,fulfilledBy){
return dispatch => {
fulfillments.create(requestId,fulfilledBy)
.then(response => response.json())
.then(fulfillment => {
dispatch(_acceptRequestSuccess(fulfillment))
})
.catch(err => {
console.log(err);
dispatch(_acceptRequestError(error))
})
}
}
I am aware that they have many middleware(s) that people suggest, but I don't
see how any of them fit this scenario unless I am completed doing somthing
incorrectly.
In my particular case, I only want to dispatch the seond action if the first is
successful, but I don't want to do this from the action creator because then
it is less reusable.
Ok, so I misunderstood you, you should mention that you are using redux-thunk.
I don't think redux action should return a promise, I think you should do everything in the component and then play with the promise, like this:
_onPress = () => {
let { request,userId} = this.props;
fulfillments.create(requestId,fulfilledBy)
.then(response => response.json())
.then(fulfillment => {
this.props.dispatch(_acceptRequestSuccess(fulfillment))
})
.then(() => {
this.props.dispatch(navigatePop());
})
.catch(err => {
console.log(err);
this.props.dispatch(_acceptRequestError(error))
})
}
But if you still want to return a promise you can make the function inside the action return the promise:
export function acceptRequest(requestId,fulfilledBy){
return dispatch => {
return fulfillments.create(requestId,fulfilledBy)
.then(response => response.json())
.then(fulfillment => {
dispatch(_acceptRequestSuccess(fulfillment))
})
.catch(err => {
console.log(err);
dispatch(_acceptRequestError(error))
})
}
}

Resources