source.uri is null coming from aws on react native - node.js

I'm sourcing the image on aws and when I run the code through i get warning error that source.uri is null and the image wont display. Im getting the image from the server cause i can see the image in the debugger but it wont display in the code.
This is my action file src/actions/item.js
import { HOST } from '../constants';
import { normalizeItems, normalizeItem } from '../utils';
export const SET_ITEMS = 'SET_ITEMS';
export function setItems(items) {
return {
type: SET_ITEMS,
items
}
}
export function getItems() {
return (dispatch, getState) => {
return fetch(`${HOST}/api/v1/items`)
.then(response => response.json())
.then(json => {
console.log("getItems", json);
if (json.is_success) {
dispatch(setItems(normalizeItems(json.items)));
} else {
alert(json.error);
}
})
.catch(e => alert(e));
}
}
This the image of the debugger shows the i have the image there
This is my reducers file src/reducers/item.js
import { SET_ITEMS,SET_ITEM } from '../actions/item';
const initialState = {
items: [],
};
export default function(state = initialState, action) {
if (action.type === SET_ITEMS) {
return {
...state,
items: action.items
}
}
This file where i render my code src/components/MainScreen/ExploreTab.js
class ExploreTab extends Component {
componentWillMount() {
this.props.getItems();
}
onPress(item) {
this.props.navigate({ routeName: "Item", params: { item: item } });
}
render() {
const { items, filter } = this.props;
return (
<FlatList
style={styles.container}
data = { items }
renderItem={({item}) =>
<TouchableOpacity onPress={() => this.onPress(item)} style={styles.item}>
<Image style={styles.image} source = {{uri: item.image}} />
<Text style = {styles.title}>{`$${item.price} ${item.instant ? '🎉 ' : ''}${item.title}`}</Text>
<Text>{`${item.itemCategory} - ${item.itemCondition} `}</Text>
</TouchableOpacity>
}
keyExtractor={(item, index) => item.id}
/>
);
}
}
const mapStateToProps = state => ({
items: state.item.items
});
const mapDispatchToProps = dispatch => ({
navigate: (route) => dispatch(navigate(route)),
getItems: () => dispatch(getItems()),
});
if I change this line
<Image style={styles.image} source = {{uri: item.image}} />
to this I will see the image
<Image style={styles.image} source = {{uri: 'https://s3.us-east-2.amazonaws.com/borroup/photos/images/1/medium/Screen_Shot_2018-03-22_at_10.48.28_PM.png'}} />

In the src/utils/index.js
I had setup as
import { HOST } from '../constants';
export function normalizeItems(items) {
return items.map(item => {
return{
id: item.id || '',
title: item.item_name ||'',
image: `${HOST}${item.image}` ||'',
itemCategory: item.item_category ||'',
itemCondition: item.item_condition ||'',
price: item.price ||'',
instant: item.instant ||'',
}
})
}
so i had to change
image: `${HOST}${item.image}` ||'',
to this and worked for me
image: `${item.image}` ||'',

Related

When clicking on detect a face even witout entering url the numbers are still moving up

i am currenty using the Clarifai API to detect faces, i also created that whenever i detect a face the numbers are moving up
see below imageurl image
however, when i click on detect, even without entering any url, the number still moves up, how can i prevent it from moving up when nothing is entered,
see my code below
FRONTEND code App.js
import React, { Component } from 'react';
import Particles from 'react-particles-js';
import FaceRecognition from './components/FaceRecognition/FaceRecognition';
import Navigation from './components/Navigation/Navigation';
import Signin from './components/Signin/Signin';
import Register from './components/Register/Register';
import Logo from './components/Logo/Logo';
import ImageLinkForm from './components/ImageLinkForm/ImageLinkForm';
import Rank from './components/Rank/Rank';
import './App.css';
const particlesOptions = {
particles: {
number: {
value: 30,
density: {
enable: true,
value_area: 800
}
}
}
}
const initialState = {
input: '',
imageUrl: '',
box: {},
route: 'signin',
isSignedIn: false,
user: {
id: '',
name: '',
email: '',
entries: 0,
joined: ''
}
}
class App extends Component {
constructor() {
super();
this.state = initialState;
}
loadUser = (data) => {
this.setState({user: {
id: data.id,
name: data.name,
email: data.email,
entries: data.entries,
joined: data.joined
}})
}
calculateFaceLocation = (data) => {
const clarifaiFace = data.outputs[0].data.regions[0].region_info.bounding_box;
const image = document.getElementById('inputimage');
const width = Number(image.width);
const height = Number(image.height);
return {
leftCol: clarifaiFace.left_col * width,
topRow: clarifaiFace.top_row * height,
rightCol: width - (clarifaiFace.right_col * width),
bottomRow: height - (clarifaiFace.bottom_row * height)
}
}
displayFaceBox = (box) => {
this.setState({box: box});
}
onInputChange = (event) => {
this.setState({input: event.target.value});
}
onButtonSubmit = () => {
this.setState({imageUrl: this.state.input});
fetch('https://ancient-sea-46547.herokuapp.com/imageurl', {
method: 'post',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
input: this.state.input
})
})
.then(response => response.json())
.then(response => {
if (response) {
fetch('https://ancient-sea-46547.herokuapp.com/image', {
method: 'put',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: this.state.user.id
})
})
.then(response => response.json())
.then(count => {
this.setState(Object.assign(this.state.user, { entries: count}))
})
.catch(console.log)
}
this.displayFaceBox(this.calculateFaceLocation(response))
})
.catch(err => console.log(err));
}
onRouteChange = (route) => {
if (route === 'signout') {
this.setState(initialState)
} else if (route === 'home') {
this.setState({isSignedIn: true})
}
this.setState({route: route});
}
render() {
const { isSignedIn, imageUrl, route, box } = this.state;
return (
<div className="App">
<Particles className='particles'
params={particlesOptions}
/>
<Navigation isSignedIn={isSignedIn} onRouteChange={this.onRouteChange} />
{ route === 'home'
? <div>
<Logo />
<Rank
name={this.state.user.name}
entries={this.state.user.entries}
/>
<ImageLinkForm
onInputChange={this.onInputChange}
onButtonSubmit={this.onButtonSubmit}
/>
<FaceRecognition box={box} imageUrl={imageUrl} />
</div>
: (
route === 'signin'
? <Signin loadUser={this.loadUser} onRouteChange={this.onRouteChange}/>
: <Register loadUser={this.loadUser} onRouteChange={this.onRouteChange}/>
)
}
</div>
);
}
}
export default App;
BACKEND code image.js
const Clarifai = require('clarifai');
const app = new Clarifai.App({
apiKey: '378c71a79572483d9d96c7c88cb13a7a'
});
const handleApiCall = (req, res) => {
app.models
.predict(Clarifai.FACE_DETECT_MODEL, req.body.input)
.then(data => {
res.json(data);
})
.catch(err => res.status(400).json('unable to work with API'))
}
const handleImage = (req, res, db) => {
const { id } = req.body;
db('users').where('id', '=', id)
.increment('entries', 1)
.returning('entries')
.then(entries => {
res.json(entries[0].entries)
})
.catch(err => res.status(400).json('unable to get entries'))
}
module.exports = {
handleImage,
handleApiCall
}
anything i can add to prevent it?
It seems the issue is with how you handle state object, and not with the Clarifai API. For example, instead of directly modifying the state using this.state, try using this.setState(). This way, when a value in the state object changes, the component will re-render, implying that the output will change according to the new values of the detected faces.
i figured the issue,
My frontend logic woudlnt work because I'm just returning a JSON object and not assigning any status code as such. So when i receive a JSON response you cannot say if(response) because in both the cases of success and failure you get a JSON and your if condition will always be true. So instead, i just wrapped the fetch call
with an if condition saying if(this.state.input) so that you handle the case where users cannot click on a button without entering an URL

How to make reusable pagination with react and redux?

On my application i'm using Reduxjs/toolkit for state management and TypeScript for type safety.
My backend were wrote in Node.js with MongoDB.
I have implemented pagination for one slice/component, and i know that is not the best solution and i want to improve it and make reusable for other slices.
Could you help me with that? Give me some hints?
Below is my current pagination implementation:
// CategorySlice
interface InitialState {
categories: ICategory[];
isFetching: boolean;
errorMessage: string | null;
// to refactor
currentPage: number;
itemsPerPage: number;
totalResults: number;
}
const initialState: InitialState = {
categories: [],
isFetching: false,
errorMessage: '',
// to refactor
currentPage: 1,
itemsPerPage: 9,
totalResults: 0,
};
export const fetchCategories = createAsyncThunk<
{ data: ICategory[]; totalResults: number },
number
>('category/fetchCategories', async (currentPage, { rejectWithValue }) => {
try {
const accessToken = getToken();
if (!accessToken) rejectWithValue('Invalid token');
const config = {
headers: { Authorization: `Bearer ${accessToken}` },
};
const response: IApiResponse<ICategoryToConvert[]> = await api.get(
`/categories?page=${currentPage}&limit=9&isPrivate[ne]=true`,
config
);
const data = response.data.data;
const convertedData = data.map(e => {
return {
id: e._id,
name: e.name,
image: e.image,
};
});
return {
totalResults: response.data.totalResults,
data: convertedData,
};
} catch (error) {
removeToken();
return rejectWithValue(error);
}
});
export const categorySlice = createSlice({
name: 'category',
initialState,
reducers: {
setNextPage(state, { payload }) {
state.currentPage = payload;
},
},
extraReducers: builder => {
builder.addCase(fetchCategories.pending, state => {
state.isFetching = true;
state.errorMessage = null;
});
builder.addCase(fetchCategories.fulfilled, (state, action) => {
state.categories = action.payload.data;
state.isFetching = false;
state.totalResults = action.payload.totalResults;
});
builder.addCase(fetchCategories.rejected, state => {
state.isFetching = false;
state.errorMessage = 'Problem with fetching categories 🐱‍👤';
});
},
});
// Category Page
const CategoryPage = () => {
const dispatch = useAppDispatch();
const { currentPage } = useAppSelector(state => state.category);
useEffect(() => {
dispatch(fetchCategories(currentPage));
}, [dispatch, currentPage]);
return (
<ContainerWrapper>
<CategoryList />
</ContainerWrapper>
);
};
export default CategoryPage;
Inside CategoryPage
I'm passing those properties from state selector.
<Pagination
currentPage={currentPage}
itemsPerPage={itemsPerPage}
paginate={(n: number) => dispatch(categoryActions.setNextPage(n))}
totalItems={totalResults}
/>
And finally PaginationComponent
interface IProps {
itemsPerPage: number;
totalItems: number;
paginate: (numb: number) => void;
currentPage: number;
}
const Pagination = ({ itemsPerPage, totalItems, paginate, currentPage }: IProps) => {
const numberOfPages = [];
for (let i = 1; i <= Math.ceil(totalItems / itemsPerPage); i++) {
numberOfPages.push(i);
}
return (
<nav className={styles['pagination']}>
<ul className={styles['pagination__list']}>
{numberOfPages.map(number => {
return (
<li
key={number}
className={`${styles['pagination__item']} ${
currentPage === number && styles['pagination__item--active']
}`}
onClick={() => paginate(number)}
>
<div className={styles['pagination__link']}>{number}</div>
</li>
);
})}
</ul>
</nav>
);
};
export default Pagination;

Why do I have to refresh the page when I delete a post? MERN stack

I am a beginner in the MERN stack and I am interested in why I have to refresh the page after deleting the document (post)?
This is my Action.js
export const deletePost = id => async (dispatch, getState) => {
try {
dispatch({ type: DELETE_POST_BEGIN });
const {
userLogin: { userInfo },
} = getState();
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.delete(`/api/v1/post/${id}`, config);
dispatch({ type: DELETE_POST_SUCCESS, payload: data });
} catch (error) {
dispatch({
type: DELETE_POST_FAIL,
payload: { msg: error.response.data.msg },
});
}
};
This is my Reducer.js
export const deletePostReducer = (state = {}, action) => {
switch (action.type) {
case DELETE_POST_BEGIN:
return { loading: true };
case DELETE_POST_SUCCESS:
return { loading: false };
case DELETE_POST_FAIL:
return { loading: false, error: action.payload.msg };
default:
return state;
}
};
And this is my Home page where i list all posts:
import { useEffect } from 'react';
import { Col, Container, Row } from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';
import { getPosts } from '../actions/postActions';
import Loader from '../components/Loader';
import Message from '../components/Message';
import Post from '../components/Post';
const HomePage = () => {
const dispatch = useDispatch();
const allPosts = useSelector(state => state.getPosts);
const { loading, error, posts } = allPosts;
const deletePost = useSelector(state => state.deletePost);
const { loading: loadingDelete } = deletePost;
useEffect(() => {
dispatch(getPosts());
}, [dispatch]);
return (
<Container>
{loading || loadingDelete ? (
<Loader />
) : error ? (
<Message variant='danger'>{error}</Message>
) : (
<>
<Row>
{posts.map(post => (
<Col lg={4} key={post._id} className='mb-3'>
<Post post={post} />
</Col>
))}
</Row>
</>
)}
</Container>
);
};
export default HomePage;
And this is my single Post component:
const Post = ({ post }) => {
const dispatch = useDispatch();
const allPosts = useSelector(state => state.getPosts);
const { loading, error, posts } = allPosts;
const userLogin = useSelector(state => state.userLogin);
const { userInfo } = userLogin;
const handleDelete = id => {
dispatch(deletePost(id));
};
return (
<>
<div>{post.author.username}</div>
<Card>
<Card.Img variant='top' />
<Card.Body>
<Card.Title>{post.title}</Card.Title>
<Card.Text>{post.content}</Card.Text>
<Button variant='primary'>Read more</Button>
{userInfo?.user._id == post.author._id && (
<Button variant='danger' onClick={() => handleDelete(post._id)}>
Delete
</Button>
)}
</Card.Body>
</Card>
</>
);
};
And my controller:
const deletePost = async (req, res) => {
const postId = req.params.id;
const post = await Post.findOne({ _id: postId });
if (!post.author.equals(req.user.userId)) {
throw new BadRequestError('You have no permission to do that');
}
await Post.deleteOne(post);
res.status(StatusCodes.NO_CONTENT).json({
post,
});
};
I wish someone could help me solve this problem, it is certainly something simple but I am a beginner and I am trying to understand.
I believe the issue is that you are not fetching the posts after delete is successful.
Try this inside the HomePage component:
...
const [isDeleting, setIsDeleting] = useState(false);
const { loading: loadingDelete, error: deleteError } = deletePost;
useEffect(() => {
dispatch(getPosts());
}, [dispatch]);
useEffect(() => {
if (!deleteError && isDeleting && !loadingDelete) {
dispatch(getPosts());
}
setIsDeleting(loadingDelete);
}, [dispatch, deleteError, isDeleting, loadingDelete]);
...
Another method is to use "filtering", but you have to update your reducer as such:
export const deletePostReducer = (state = {}, action) => {
switch (action.type) {
case DELETE_POST_BEGIN:
return { loading: true };
case DELETE_POST_SUCCESS:
return { loading: false, data: action.payload}; // <-- this was changed
case DELETE_POST_FAIL:
return { loading: false, error: action.payload.msg };
default:
return state;
}
};
Now in your HomePage component, you will do something like this when rendering:
...
const { loading: loadingDelete, data: deletedPost } = deletePost;
...
useEffect(() => {
dispatch(getPosts());
if (deletedPost) {
console.log(deletedPost);
}
}, [dispatch, deletedPost]);
return (
...
<Row>
{posts.filter(post => post._id !== deletedPost?._id).map(post => (
<Col lg={4} key={post._id} className='mb-3'>
<Post post={post} />
</Col>
))}
</Row>
)

How to update the user feed after updating the post?

I have a UserFeed component and EditForm component. As soon as I edit the form, I need to be redirected to the UserFeed and the updated data should be shown on UserFeed(title and description of the post).
So, the flow is like-UserFeed, which list the posts, when click on edit,redirected to EditForm, updates the field, redirected to UserFeed again, but now UserFeed should list the posts with the updated data, not the old one.
In this I'm just redirectin to / just to see if it works. But I need to be redirected to the feed with the updated data.
EditForm
import React, { Component } from "react";
import { connect } from "react-redux";
import { getPost } from "../actions/userActions"
class EditForm extends Component {
constructor() {
super();
this.state = {
title: '',
description: ''
};
handleChange = event => {
const { name, value } = event.target;
this.setState({
[name]: value
})
};
componentDidMount() {
const id = this.props.match.params.id
this.props.dispatch(getPost(id))
}
componentDidUpdate(prevProps) {
if (prevProps.post !== this.props.post) {
this.setState({
title: this.props.post.post.title,
description: this.props.post.post.description
})
}
}
handleSubmit = () => {
const id = this.props.match.params.id
const data = this.state
this.props.dispatch(updatePost(id, data, () => {
this.props.history.push("/")
}))
}
render() {
const { title, description } = this.state
return (
<div>
<input
onChange={this.handleChange}
name="title"
value={title}
className="input"
placeholder="Title"
/>
<textarea
onChange={this.handleChange}
name="description"
value={description}
className="textarea"
></textarea>
<button>Submit</button>
</div>
);
}
}
const mapStateToProps = store => {
return store;
};
export default connect(mapStateToProps)(EditForm)
UserFeed
import React, { Component } from "react"
import { getUserPosts, getCurrentUser } from "../actions/userActions"
import { connect } from "react-redux"
import Cards from "./Cards"
class UserFeed extends Component {
componentDidMount() {
const authToken = localStorage.getItem("authToken")
if (authToken) {
this.props.dispatch(getCurrentUser(authToken))
if (this.props && this.props.userId) {
this.props.dispatch(getUserPosts(this.props.userId))
} else {
return null
}
}
}
render() {
const { isFetchingUserPosts, userPosts } = this.props
return isFetchingUserPosts ? (
<p>Fetching....</p>
) : (
<div>
{userPosts &&
userPosts.map(post => {
return <Cards key={post._id} post={post} />
})}
</div>
)
}
}
const mapStateToPros = state => {
return {
isFetchingUserPosts: state.userPosts.isFetchingUserPosts,
userPosts: state.userPosts.userPosts.userPosts,
userId: state.auth.user._id
}
}
export default connect(mapStateToPros)(UserFeed)
Cards
import React, { Component } from "react"
import { connect } from "react-redux"
import { compose } from "redux"
import { withRouter } from "react-router-dom"
class Cards extends Component {
handleEdit = _id => {
this.props.history.push(`/post/edit/${_id}`)
}
render() {
const { _id, title, description } = this.props.post
return (
<div className="card">
<div className="card-content">
<div className="media">
<div className="media-left">
<figure className="image is-48x48">
<img
src="https://bulma.io/images/placeholders/96x96.png"
alt="Placeholder image"
/>
</figure>
</div>
<div className="media-content" style={{ border: "1px grey" }}>
<p className="title is-5">{title}</p>
<p className="content">{description}</p>
<button
onClick={() => {
this.handleEdit(_id)
}}
className="button is-success"
>
Edit
</button>
</div>
</div>
</div>
</div>
)
}
}
const mapStateToProps = state => {
return {
nothing: "nothing"
}
}
export default compose(withRouter, connect(mapStateToProps))(Cards)
updatePost action
export const updatePost = (id, data, redirect) => {
return async dispatch => {
dispatch( { type: "UPDATING_POST_START" })
try {
const res = await axios.put(`http://localhost:3000/api/v1/posts/${id}/edit`, data)
dispatch({
type: "UPDATING_POST_SUCCESS",
data: res.data
})
redirect()
} catch(error) {
dispatch({
type: "UPDATING_POST_FAILURE",
data: { error: "Something went wrong"}
})
}
}
}
I'm not sure if my action is correct or not.
Here's the updatePost controller.
updatePost: async (req, res, next) => {
try {
const data = {
title: req.body.title,
description: req.body.description
}
const post = await Post.findByIdAndUpdate(req.params.id, data, { new: true })
if (!post) {
return res.status(404).json({ message: "No post found "})
}
return res.status(200).json({ post })
} catch(error) {
return next(error)
}
}
One mistake is that to set the current fields you need to use $set in mongodb , also you want to build the object , for example if req.body does not have title it will generate an error
updatePost: async (req, res, next) => {
try {
const data = {};
if(title) data.title=req.body.title;
if(description) data.description=req.body.description
const post = await Post.findByIdAndUpdate(req.params.id, {$set:data}, { new: true })
if (!post) {
return res.status(404).json({ message: "No post found "})
}
return res.status(200).json({ post })
} catch(error) {
return next(error)
}
}

React native, redux and axios : UnhandledPromiseRejectionWarning

I have an app where you can create many events, and I have created an API with express and node JS. In the react-native projet, I use Axios to fetch with API. But I have this weird error in my terminal :
(node:59293) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): RangeError: Invalid status code: 0
(node:59293) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
When I try to create an event, and in my browser console I have this :
Error: Network Error
at createError (createError.js:15)
at XMLHttpRequest.handleError (xhr.js:87)
at XMLHttpRequest.dispatchEvent (event-target.js:172)
at XMLHttpRequest.setReadyState (XMLHttpRequest.js:542)
at XMLHttpRequest.__didCompleteResponse (XMLHttpRequest.js:378)
at XMLHttpRequest.js:482
at RCTDeviceEventEmitter.emit (EventEmitter.js:181)
at MessageQueue.__callFunction (MessageQueue.js:242)
at MessageQueue.js:108
at guard (MessageQueue.js:46)
I paste my code here, maybe I'm wrong somewhere,
BACK END PART
import Event from './model';
export const createEvent = async (req, res) => {
const { title, description } = req.body;
const newEvent = new Event({ title, description });
try {
return res.status(201).json({ event: await newEvent.save() });
} catch(e) {
return res.status(e.status).json({ error: true, message: 'Error with event' });
}
};
export const getAllEvents = async (req, res) => {
try {
return res.status(200).json({ events: await Event.find({} )});
} catch(e) {
return res.status(e.status).json({ error: true, message: 'Error with all events' });
}
};
FRONT-END PART
api.js
import axios from 'axios';
axios.defaults.baseURL = 'http://localhost:3000/api';
class EventApi {
constructor() {
this.path = '/events';
}
async fetchEvents() {
try {
const { data } = await axios.get(this.path);
return data.events;
} catch (e) {
console.log(e);
}
}
async createEventPost(args) {
// console.log('nous entrons dans le cadre de la création dun evenement');
try {
console.log('nous tryons');
const res = await axios.post(`${this.path}/new`, { ...args });
console.log(res);
console.log('hello world', args);
return res;
} catch (e) {
console.log(e);
console.log('lol');
}
}
}
export {
EventApi
};
CreateScreen.js
import React, { Component } from 'react';
import { View } from 'react-native';
import { connect } from 'react-redux';
import DateTimePicker from 'react-native-modal-datetime-picker';
import moment from 'moment';
import { Ionicons } from '#expo/vector-icons';
import { createEvent } from './actions';
import { LoadingScreen } from '../../common';
import Colors from '../../../constants/colors';
import styles from './styles/CreateScreen';
import CreateEventsForm from './components/CreateEventsForm';
#connect(
state => ({
event: state.createEvent
}),
{ createEvent }
)
export default class CreateScreen extends Component {
static navigationOptions = {
title: 'Créer un événement',
header: {
style: {
backgroundColor: Colors.whiteColor
},
titleStyle: {
color: Colors.redParty
}
},
tabBar: {
icon: ({ tintColor }) => (
<Ionicons name="ios-create" size={25} color={tintColor} />
)
}
}
state = {
isDateTimePickerVisible: false,
date: moment()
}
_showDateTimePicker = () => this.setState({ isDateTimePickerVisible: true })
_handleDateTimePicker = () => this.setState({ isDateTimePickerVisible: false })
_handleDatePicked = date => {
this.setState({ date });
this._handleDateTimePicker();
}
_checkTitle() {
const { date } = this.state;
if (date > moment()) {
return moment(date).format('MMMM Do YYYY, h:mm.ss a');
}
return 'Choisir une date';
}
_checkNotEmpty() {
const { date } = this.state;
if (date > moment()) {
return false;
}
return true;
}
_createEvent = async values => {
await this.props.createEvent(values);
this.props.navigation.goBack();
}
render() {
const { event } = this.props;
if (event.isLoading) {
return (
<View style={styles.root}>
<LoadingScreen />
</View>
);
} else if (event.error.on) {
return (
<View>
<Text>
{event.error.message}
</Text>
</View>
);
}
return (
<View style={styles.root}>
<CreateEventsForm
createEvent={this._createEvent}
showDateTimePicker={this._showDateTimePicker}
checkTitle={this._checkTitle()}
/>
<DateTimePicker
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this._handleDatePicked}
onCancel={this._handleDateTimePicker}
mode="datetime"
/>
</View>
);
}
}
acion.js
import { EventApi } from '../../../constants/api';
import { fetchMyEvents } from '../home/actions';
const eventApi = new EventApi();
export const CREATE_EVENT = 'CREATE_EVENT';
export const CREATE_EVENT_SUCCESS = 'CREATE_EVENT_SUCCESS';
export const CREATE_EVENT_ERROR = 'CREATE_EVENT_ERROR';
export const createEvent = args => async dispatch => {
dispatch({ type: CREATE_EVENT });
try {
await eventApi.createEventPost(args);
dispatch({ type: CREATE_EVENT_SUCCESS });
} catch (e) {
return dispatch({ type: CREATE_EVENT_ERROR });
}
return await dispatch(fetchMyEvents());
};
reducer.js
import { CREATE_EVENT, CREATE_EVENT_ERROR, CREATE_EVENT_SUCCESS } from './actions';
const INITIAL_STATE = {
error: {
on: false,
message: null
},
isLoading: false
};
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case CREATE_EVENT:
return {
...INITIAL_STATE,
isLoading: true
};
case CREATE_EVENT_SUCCESS:
return {
...INITIAL_STATE,
isLoading: false
};
case CREATE_EVENT_ERROR:
return {
error: {
on: true,
message: 'Error happened'
},
isLoading: false
};
default:
return state;
}
};
Don't hesitate to ask if you need more code (for example the CreateEventsForm)
Thank you !
It looks like the original error is being swallowed. One solution I found for a similar problem seems to be to drop the version of react-native - https://github.com/mzabriskie/axios/issues/640, but a better approach would to be to discover the original error and then you should be able to address that - https://www.webkj.com/react-native/javascript-error-unhandled-promise-rejection-warning :

Resources