i need to fetch some data before render my template and i tryied 2 differents methods, but the both failed.
this is the first one with sync transaction:
if (loginData) {
loginGet(userData!.cpf, loginData.access_token)
.then((data: UserAzureInterface) => {
console.log(JSON.stringify(data));
dispatchUserAzureSuccess(data, dispatch);
})
.catch(_error => {});
} else {
navigation.navigate('Login');
}
return (
<>
<ProfileIndexTemplate onSubmit={onSubmit} userData={userData} />
</>
);
and this is the async transaction:
const getLoginAzure = async () => {
if (loginData) {
const loginAzureData = await loginGet(
userData!.cpf,
loginData.access_token,
);
console.log(JSON.stringify(loginAzureData));
dispatchUserAzureSuccess(loginAzureData, dispatch);
}
};
getLoginAzure();
return (
<>
<ProfileIndexTemplate onSubmit={onSubmit} userData={userData} />
</>
);
From profileIndexTemplate im trying to get my UserAzureInterface but i got undefined data, because my loginGet at the screen are not finish yet.
const loginAzure = useSelector(({ userAzure }: AppState) => userAzure.data);
console.log(`meu login azure: ${JSON.stringify(loginAzure)}`);
Can i see the error, but i cant figure how to solve that. any one can helps me?
i got it! to solve this problem this is what i did:
useEffect(() => {
console.log(`gettingAzure: ${userData!.cpf}`);
if (!loginData) {
navigation.navigate('Login');
} else {
loginGet(userData!.cpf, loginData!.access_token)
.then((data: UserAzureInterface) => {
console.log(JSON.stringify(data));
dispatchUserAzureSuccess(data, dispatch);
})
.catch(_error => {});
}
}, []);
if (azurePending || !azureData) {
return <LoadingModal />;
}
return (
<ProfileIndexTemplate
onSubmit={onSubmit}
userData={userData}
loginAzure={azureData}
/>
);
Related
I am Selecting Multiple Files and using Multer saving Files to a specific folder. But if i am uploading Single file it is working Fine but if Selected More than two it is giving me an
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client. I am frustrated solving it. Can anyone one help me out yrr.
<div className="mb-3" >
<CFormLabel htmlFor="formFileMultiple">Select Resources</CFormLabel>
<CFormInput
multiple
onChange={(event) => formikProps.setFieldValue('fileName', event.target.files)}
accept="application/pdf, application/zip"
type="file" id="formFileMultiple" />
<p style={{ color: 'red' }}>{formikProps.touched.fileName && formikProps.errors.fileName}</p>
</div>
const handleAddResources = async ({ fileName }) => {
try {
const data = new FormData();
// data.append("fileName", fileName);
data.append("courseId", props.currentUser.item.course_id);
for (let i = 0; i < fileName.length; i++) {
// newArr.push(fileName[i]);
data.append("fileName", fileName[i]);
let response = await axios.post(`${ConfigData.SERVER_URL}/admin/resources/addResources`, data, {
})
if (response.data.status == false) {
throw Error(response.data.message)
}
else {
console.log("Success")
setthrowAlert(true);
}
}
} catch (error) { console.log(error) }
}
router.post('/addResources', fileUpload.array('fileName', 100), async (req, res) => {
try {
if (req.body && req.files) {
req.files.map(async(item) => {
console.log("ITEM--->", item);
let ResourcePost = new ResourcesPost({
originalname: item.originalname,
FileName:item.filename,
courseId: req.body.courseId,
mimetype:item.mimetype,
encoding:item.encoding,
size:item.size,
destination:item.destination
})
let uploadData = await ResourcePost.save()
if (uploadData) {
res.status(200).json({ status: true, data: uploadData })
} else {
res.status(500).json({ status: false, message: err.message })
}
})
} else {
console.log("Resourses Not Found !");
}
}
catch (error) {
console.log(error);
}
})
I'm getting the error Cannot read property 'createEvent' of null when I use setTimeout in the code to wait for a while before navigating. The timeout is needed for a reason. The test is passing when I remove the timeout but need to make it work with the timeout really.
Here is the code I have.
useEffect(() => {
(async () => {
if (hasInternetConnection) {
...
} else {
setTimeout(() => {
navigation.dispatch(state => {
const routes = state.routes.filter(route => route.name === splashScreen)
routes.push({ name: homeNavigation, params: { screen: offlineDashboardScreen } })
return CommonActions.reset({
...state,
routes,
index: routes.length - 1
})
})
}, 1000)
}
})()
}, [hasInternetConnection, conductor])
it('navigates OfflineDashboardScreen if there is no internet connection', async () => {
useNetInfo.mockReturnValueOnce({
type: 'test', // not 'unknown'
isInternetReachable: false,
details: {},
isConnected: false
})
const component = (
<NavigationContainer>
<AppProviders>
<ThemeProvider theme={mockTheme}>
<AppNavigation/>
</ThemeProvider>
</AppProviders>
</NavigationContainer>
)
const rendered = render(component)
expect(await rendered.findByText(strings.om1)).toBeTruthy()
})
I've added jest.useFakeTimers() to setup files.
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>
)
Please I would be happy if anyone would help me
I have a problem, I can not use the server-side functions, I call the functions with axios, and execute it in react hooks.
I actually build chat, which is why I use react hook, because I want messages to be updated all the time.
I also use firestore. There I save the messages, and receive them through the server side function.
It's a component of the chat - it's causing me problems, I do not understand why.
The server side functions work great, I tested them in postman, and they worked. The problem is that I can't run them in a function component. I do not know what I'm doing wrong.
The error I get here is in the line chat.users.length> 0?, When I make this comparison I get that chat.users is undefined, but I do not understand why because I initialize it at first, using a server side function , Which gives the necessary information
I'm very confused, and I'm new here on the site, I'm trying to figure out why it has not worked for two whole days
I think I might be confused by syntax, for example using an unnecessary dispatch inside component of the chat
i got this error:
enter image description here
component of the chat
import React, { useEffect, useState } from 'react';
import './style.css';
import { useDispatch, useSelector } from 'react-redux';
import { getRealtimeUsers, updateMessage, getRealtimeConversations } from '../../redux/actions/chatActions';
import { Fragment } from 'react';
const User = (props) => {
const { chat, onClick } = props;
return (
<div onClick={() => onClick(chat)} className="displayName">
<div className="displayPic">
<img src="https://i.pinimg.com/originals/be/ac/96/beac96b8e13d2198fd4bb1d5ef56cdcf.jpg" alt="" />
</div>
<div style={{ display: 'flex', flex: 1, justifyContent: 'space-between', margin: '0 10px' }}>
<span style={{ fontWeight: 500 }}>{chat.firstName} {chat.lastName}</span>
<span className={chat.isOnline ? `onlineStatus` : `onlineStatus off`}></span>
</div>
</div>
);
}
const HomePage = (props) => {
const dispatch = useDispatch();
const user = useSelector(state => state.user.credentials);
const chat = useSelector(state => state.chat);
const [chatStarted, setChatStarted] = useState(false);
const [chatUser, setChatUser] = useState('');
const [message, setMessage] = useState('');
const [userUid, setUserUid] = useState(null);
let unsubscribe;
useEffect(() => {
//unsubscribe = dispatch(getRealtimeUsers(user.handle))
dispatch(getRealtimeUsers());
}, []);
//console.log(user);
//componentWillUnmount
useEffect(() => {
return () => {
//cleanup
//unsubscribe.then(f => f()).catch(error => console.log(error));
unsubscribe.then(f => f()).catch(error => console.log(error));
}
}, []);
//function
const initChat = (chat) => {
setChatStarted(true)
setChatUser(`${chat.firstName} ${chat.lastName}`)
setUserUid(chat.handle);
console.log(chat);
dispatch(getRealtimeConversations({ uid_1: user.handle, uid_2: chat.handle }));
}
const submitMessage = (e) => {
const msgObj = {
user_uid_1: user.handle,
user_uid_2: userUid,
message
}
if (message !== "") {
dispatch(updateMessage(msgObj))
.then(() => {
setMessage('')
});
}
//console.log(msgObj);
}
return (
<Fragment>
<section className="container">
<div className="listOfUsers">
{console.log(chat)}
{
//chat.users != undefined
chat.users.length > 0 ?
chat.users.map(user => {
return (
<User
onClick={initChat}
key={user.handle}
user={user}
/>
);
})
: null
}
</div>
<div className="chatArea">
<div className="chatHeader">
{
chatStarted ? chatUser : ''
}
</div>
<div className="messageSections">
{
chatStarted ?
chat.conversations.map(con =>
<div style={{ textAlign: con.user_uid_1 == user.handle ? 'right' : 'left' }}>
<p className="messageStyle" >{con.message}</p>
</div>)
: null
}
</div>
{
chatStarted ?
<div className="chatControls">
<textarea
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="Write Message"
/>
<button onClick={submitMessage}>Send</button>
</div> : null
}
</div>
</section>
</Fragment>
);
}
export default HomePage;
This is the axios:
app.get('/realtimeUsers', FBAuth, getRealtimeUsers );
app.post('/updateMessage', FBAuth, updateMessage);
app.get('/realtimeConversations', FBAuth, getRealtimeConversations);
And this is the server side functions - They work 100% - I checked them many times and they worked.:
const { db } = require('../util/admin');
exports.getRealtimeUsers = (req, res) => {
db.collection("users")
.onSnapshot((querySnapshot) => {
const users = [];
querySnapshot.forEach(function (doc) {
if (doc.data().handle != req.user.handle) {
users.push(doc.data());
}
});
return res.json(users);
});
}
exports.updateMessage = (req, res) => {
db.collection('conversations')
.add({
...req.body,
isView: false,
createdAt: new Date()
})
.then(() => {
return res.json({ message: "Conversations added successfully" });
})
.catch((err) => {
console.error(err);
return res.status(500).json({ error: err.code });
});
}
exports.getRealtimeConversations = (req, res) => {
console.log(JSON.stringify("testing"));
console.log(JSON.stringify(req.query));
console.log(JSON.parse(req.query.user));
console.log(JSON.parse(req.query.user).uid_1);
console.log(JSON.parse(req.query.user).uid_2);
db.collection('conversations')
.where('user_uid_1', 'in', [JSON.parse(req.query.user).uid_1, JSON.parse(req.query.user).uid_2])
.orderBy('createdAt', 'asc')
.onSnapshot((querySnapshot) => {
const conversations = [];
querySnapshot.forEach(doc => {
console.log(JSON.stringify(doc));
if (
(doc.data().user_uid_1 == JSON.parse(req.query.user).uid_1 && doc.data().user_uid_2 == JSON.parse(req.query.user).uid_2)
||
(doc.data().user_uid_1 == JSON.parse(req.query.user).uid_2 && doc.data().user_uid_2 == JSON.parse(req.query.user).uid_1)
) {
conversations.push(doc.data())
}
});
console.log(conversations);
return res.json(conversations);
})
//return res.json([]);
}
this is the actions that used in the client side, here i call to the axios:
import { userConstants } from "../types";
import axios from 'axios';
export const getRealtimeUsers = () => (dispatch) => {
dispatch({ type: `${userConstants.GET_REALTIME_USERS}_REQUEST` });
axios
.get('/realtimeUsers')
.then((res) => {
console.log(res);
dispatch({
type: `${userConstants.GET_REALTIME_USERS}_SUCCESS`,
payload: res.data
});
})
.catch((err) => console.log(err))
}
export const updateMessage = (msgObj) => (dispatch) => {
axios.post('/updateMessage', msgObj)
.then(() => { })
.catch((err) => console.log(err));
}
export const getRealtimeConversations = (user) => (dispatch) => {
//user = { uid_1: "from visualcode", uid_2: "userUid" };
console.log(JSON.stringify(user));
axios.get('/realtimeConversations',
{
params: {
user: JSON.stringify(user)
//uid_1:JSON.stringify("user.handle"),
//uid_2:JSON.stringify("userUid")
}
}
)
.then((res) => {
dispatch({
type: userConstants.GET_REALTIME_MESSAGES,
payload: res.data
});
})
.catch((err) => console.log(err))
}
I am not able to understand your whole code flow, i.e., how the chat.users will be populated before initChat is called.
But still, for your problem, you should always put a check for undefined values while iterating through an array.
<div className="listOfUsers">
{console.log(chat)}
{
//chat.users != undefined
chat && chat.users && chat.users.length > 0 &&
chat.users.map(user => {
return (
<User
onClick={initChat}
key={user.handle}
user={user}
/>
);
})
}
</div>
I have a stateful component that calls a CEP promise, to fetch data from post offices. This data is fetched when the Zip input is fulfilled with 9 chars - 8 number and an '-' - and return an object with desired information.
Heres the function:
const handleZipCode = useCallback(
async ({ target }: ChangeEvent<HTMLInputElement>) => {
const { value } = target;
try {
if (value.length === 9 && isDigit(value[8])) {
const zip = await cep(value);
if (zip?.city) {
setZipData(zip);
} else
addressFormRef.current?.setErrors({
user_zip_code: 'CEP not found',
});
}
} catch (e) {
addressFormRef.current?.setErrors({
user_zip_code: e.message ?? 'CEP not found',
});
}
},
[isDigit]
);
Then, on the return I have some fields, example:
<fieldset>
<legend>Address</legend>
<Input
mask=''
name='user_address'
placeholder='Rua um dois trĂªs'
defaultValue={zipData.street}
/>
</fieldset>
Here's the Input component:
const Input: React.FC<InputProps> = ({ name, ...rest }) => {
const { fieldName, defaultValue, registerField, error } = useField(name);
const inputRef = useRef(null);
useEffect(() => {
registerField({
name: fieldName,
ref: inputRef.current,
path: 'value',
// eslint-disable-next-line
setValue(ref: any, value: string) {
ref.setInputValue(value);
},
// eslint-disable-next-line
clearValue(ref: any) {
ref.setInputValue('');
},
});
}, [fieldName, registerField]);
return (
<Container>
<ReactInputMask ref={inputRef} defaultValue={defaultValue} {...rest} />
{error && <Error>{error}</Error>}
</Container>
);
};
However the zipData seems to update, but the default value is not fulfilled. What I'm doing wrong?
The default value will not change, as unform is an uncontrolled form library, the defaultValue will be set on the first render of the page and then will not change anymore.
To fix your problem you can do something like:
// on your handleZipCode function
formRef.current.setData({
zipData: {
street: zipResult.street,
},
});