Skip to content

Commit

Permalink
add request provider
Browse files Browse the repository at this point in the history
  • Loading branch information
tigransimonyan committed Jan 5, 2024
1 parent 877f1dc commit 007b09a
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 78 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ node_modules
.parcel-cache
tmp
yarn.lock
dist
dist
yarn-error.log
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<div id="foo-comments" data-emotions="❤️,😀,🪄,🥸,💡,🤔,💩,😢" data-api-url="http://localhost:9547/api"
data-theme="light" data-language="en"></div>
<script type="module" src="src/index.js"></script>
<script src="src/index.js"></script>
</body>

</html>
9 changes: 1 addition & 8 deletions src/components/Reactions/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React, { useEffect, useCallback } from 'react';
import FingerprintJS from '@fingerprintjs/fingerprintjs';
import axios from 'axios';

import { ContentBubbleContainer, ContentBubble, ContentBubbleCount } from './style';
import { useReactionDispatch, useReactionState } from 'providers/Reactions';
Expand All @@ -14,12 +12,7 @@ function ReactionsComponent({ emotions }) {
const onReact = useCallback(reaction => actions.react(reaction), []);

useEffect(() => {
FingerprintJS.load().then(fp => {
fp.get().then(({ visitorId }) => {
axios.defaults.headers.common['fingerprint'] = visitorId;
actions.getReactions();
});
});
actions.getReactions();
}, []);

return (
Expand Down
27 changes: 15 additions & 12 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import CommentsProvider from 'providers/Comments';
import ReactionsProvider from 'providers/Reactions';
import LanguageProvider from 'providers/Language';
import ThemeProvider from 'providers/Theme';
import RequestProvider from 'providers/Requests';

import Editor from 'components/Editor';
import Comments from 'components/Comments';
Expand All @@ -20,18 +21,20 @@ if (commentsElement) {

ReactDOM.render(
<ThemeProvider theme={theme}>
<LanguageProvider language={language}>
{emotions && (
<ReactionsProvider api={api}>
<ReactionsComponent emotions={emotions} />
</ReactionsProvider>
)}
<CommentsProvider api={api}>
<Editor />
<Comments />
</CommentsProvider>
<Footer />
</LanguageProvider>
<RequestProvider apiUrl={api}>
<LanguageProvider language={language}>
{emotions && (
<ReactionsProvider>
<ReactionsComponent emotions={emotions} />
</ReactionsProvider>
)}
<CommentsProvider>
<Editor />
<Comments />
</CommentsProvider>
<Footer />
</LanguageProvider>
</RequestProvider>
</ThemeProvider>,
commentsElement
);
Expand Down
59 changes: 28 additions & 31 deletions src/providers/Comments/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import React, { useReducer, useState } from 'react';
import { ErrorMessage, Close } from './style';
import axios from 'axios';
import React, { useReducer, useCallback } from 'react';
import { useRequest } from 'providers/Requests';

const CommentsStateContext = React.createContext(undefined);
const CommentsDispatchContext = React.createContext(undefined);

const initialState = {
loading: true,
comments: [],
api: ''
comments: []
};

const reducer = (state, action) => {
Expand All @@ -35,49 +33,48 @@ const reducer = (state, action) => {
};

export default function CommentsProvider(props) {
const [error, setError] = useState('');
const pageId = `${window.location.hostname}${window.location.pathname}`;
const request = useRequest();

const [state, dispatch] = useReducer(reducer, {
...initialState,
...props
});

const addComment = data => {
return axios
.post(`${props.api}/comments`, { ...data, pageId })
.then(response =>
const addComment = useCallback(
data => {
return request.post(`/comments`, { ...data }).then(response =>
dispatch({
type: 'ADD_COMMENT',
payload: { ...data, ...response.data }
})
)
.catch(response => Promise.reject(setError(response.message)));
};
);
},
[request]
);

const removeComment = useCallback(
data => {
return request
.delete(`/comments/${data._id}?secret=${data.secret}`)
.then(() => dispatch({ type: 'REMOVE_COMMENT', payload: data }));
},
[request]
);

const removeComment = data => {
return axios
.delete(`${props.api}/comments/${data._id}?secret=${data.secret}`)
.then(() => dispatch({ type: 'REMOVE_COMMENT', payload: data }))
.catch(response => Promise.reject(setError(response.message)));
};
const getComments = useCallback(() => {
const pageId = `${window.location.hostname}${window.location.pathname}`;

const getComments = () => {
return axios
.get(`${props.api}/comments?pageId=${encodeURI(pageId)}`)
.then(response => dispatch({ type: 'GET_COMMENTS', payload: response.data }))
.catch(response => Promise.reject(setError(response.message)));
};
return request.get(`/comments?pageId=${encodeURI(pageId)}`).then(response => {
console.log('then response', response);
dispatch({ type: 'GET_COMMENTS', payload: response.data });
});
}, [request]);

return (
<CommentsStateContext.Provider value={state}>
<CommentsDispatchContext.Provider
value={{ addComment, getComments, removeComment }}
>
{error && (
<ErrorMessage>
{error} :( <Close onClick={() => setError('')} />
</ErrorMessage>
)}
{props.children}
</CommentsDispatchContext.Provider>
</CommentsStateContext.Provider>
Expand Down
43 changes: 18 additions & 25 deletions src/providers/Reactions/index.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import React, { useReducer, useState } from 'react';
import axios from 'axios';
import { ErrorMessage, Close } from '../Comments/style';
import React, { useReducer, useCallback } from 'react';
import { useRequest } from 'providers/Requests';

const ReactionStateContext = React.createContext(undefined);
const ReactionDispatchContext = React.createContext(undefined);

const initialState = {
loading: true,
reactions: [],
api: ''
reactions: []
};

const reducer = (state, action) => {
Expand Down Expand Up @@ -46,41 +44,36 @@ export function useReactionDispatch() {
}

export default function ReactionProvider(props) {
const [error, setError] = useState('');
const request = useRequest();

const pageId = `${window.location.hostname}${window.location.pathname}`;
const [state, dispatch] = useReducer(reducer, {
...initialState,
...props
});

const react = reaction => {
return axios
.post(`${props.api}/reactions`, { reaction, pageId })
.then(response =>
const react = useCallback(
reaction => {
return request.post(`/reactions`, { reaction }).then(response =>
dispatch({
type: 'REACT',
payload: response.data
})
)
.catch(response => Promise.reject(setError(response.message)));
};
);
},
[request]
);

const getReactions = useCallback(() => {
const pageId = `${window.location.hostname}${window.location.pathname}`;

const getReactions = () => {
return axios
.get(`${props.api}/reactions?pageId=${encodeURI(pageId)}`)
.then(response => dispatch({ type: 'GET_REACTIONS', payload: response.data }))
.catch(response => Promise.reject(setError(response.message)));
};
return request
.get(`/reactions?pageId=${encodeURI(pageId)}`)
.then(response => dispatch({ type: 'GET_REACTIONS', payload: response.data }));
}, [request]);

return (
<ReactionStateContext.Provider value={state}>
<ReactionDispatchContext.Provider value={{ react, getReactions }}>
{error && (
<ErrorMessage>
{error} :( <Close onClick={() => setError('')} />
</ErrorMessage>
)}
{props.children}
</ReactionDispatchContext.Provider>
</ReactionStateContext.Provider>
Expand Down
68 changes: 68 additions & 0 deletions src/providers/Requests/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import React, { useState, useMemo, useEffect } from 'react';
import axios from 'axios';
import FingerprintJS, { load } from '@fingerprintjs/fingerprintjs';
import { ErrorMessage, Close } from '../Comments/style';

const RequestContext = React.createContext(undefined);

export function useRequest() {
const context = React.useContext(RequestContext);
if (context === undefined) {
throw new Error('useRequest must be used within a RequestProvider');
}
return context;
}

export default function RequestProvider(props) {
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);

const instance = useMemo(() => {
const pageId = `${window.location.hostname}${window.location.pathname}`;

return axios.create({
baseURL: props.apiUrl,
transformRequest: [
function (data) {
return {
...data,
pageId
};
},
...axios.defaults.transformRequest
],
transformResponse: [
function (data, _headers, status) {
if (status !== 200) {
setError(data || 'Something went wrong!');
}
return data;
},
...axios.defaults.transformResponse
]
});
}, [axios, props.baseURL]);

useEffect(() => {
if (instance) {
setLoading(true);
FingerprintJS.load().then(fp => {
fp.get().then(({ visitorId }) => {
instance.defaults.headers['fingerprint'] = visitorId;
setLoading(false);
});
});
}
}, [instance]);

return (
<RequestContext.Provider value={instance}>
{error && (
<ErrorMessage>
{error} <Close onClick={() => setError('')} />
</ErrorMessage>
)}
{loading ? 'Loading...' : props.children}
</RequestContext.Provider>
);
}

0 comments on commit 007b09a

Please sign in to comment.