Three Review React Widgets
Review Grid widget | Review Slider Widget | Review Popup Widget |
I was put up with a task to develop 3 React Widgets tailored to showcasing all of our clients reviews on their website. This indeed for a company would add value not for only us but for every other small business we take under our wing. These widgets would impart honesty and authenticity of a business by allowing potential customers peak their interest.
We all want to try new places, but we must hear what other have to say first…
🧠 Brainstorming
To be honest, I dove into this without a plan really. I was still a bit new to react but I felt confident enough that I would be able to figure it out. Whilst developing I encountered better practices and understandings on how to make this better and of course faster. I learned so much about reactivity, and how to handle re renders and such. So with anyone struggling I say start out with some sort of widget.
Review Grid Widget
a layout grid review card mosiac format, infinite scroll
Review Slider Widget
a slideshow of review cards, limited to 3-15 reviews in a slider
Review Single(popup) Widget
a popup and expandable widget that will display, infinite scroll
🧰 ToolKit
- React
- TS
- Vite
- Mantine Component Library
- TanStack React Query
- NO tailwind (just wasn’t under my radar)
⚙️ Configuration
I am about to quite possibly save you hours of research. I’ve spent maybe a day and a half maybe longer finding a solution to immediately execute react projects.
format:'iife'
yeah that’s it… More specifically Rollup JS.
vite.config.ts
const leadingPath = 'widgets/stu-react-reviews-grid/';
// https://vitejs.dev/config/
export default defineConfig({
base: './',
plugins: [react(),viteTsconfigPaths(), svgrPlugin(), ],
resolve:{
preserveSymlinks: true,
},
//Cache Busting
build: {
rollupOptions: {
output: {
format:'iife',
dir: 'dist',
entryFileNames: `assets/stu-reviews-grid.js`,
chunkFileNames: `assets/stu-reviews-grid.js`,
assetFileNames: `assets/stu-reviews-grid.[ext]`
}
}
},
});
Lets add in another div with an id we want in our index.html, lets maintain this name. Through our project (easy solution for consistency, I should’ve used env variables smh)
<div id="stu-reviews-grid"></div>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/widgets/stu-react-reviews-grid/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="SoTellUs Reviews Grid Widget"/>
<link rel="apple-touch-icon" href="/widgets/stu-react-reviews-grid/logo192.png" />
<link rel="manifest" href="/widgets/stu-react-reviews-grid/manifest.json" />
<title>SoTellUs Reviews Grid Widget</title>
</head>
<body style="background-color: transparent;">
<noscript>You need to enable JavaScript to run this app.</noscript>
<script type="module" src="/src/index.tsx"></script>
<div id="stu-reviews-grid"></div>
</body>
</html>
index.tsx
const queryClient = new QueryClient({ defaultOptions: { queries: { suspense: true } } });
const _DEV = import.meta.env.DEV;
const el = document.getElementById('stu-reviews-grid') as HTMLElement;
if (_DEV && el === null) throw new Error('DEV_MODE: STU is missing DIV element with parameters');
const params = new URLSearchParams(window.location.search);
const p_uid = params.get('uid');
const p_h = params.get('h');
const p_w = params.get('w');
const uid = p_uid !== null ? p_uid : el.getAttribute('data-uid') ? el.getAttribute('data-uid') : "";
const height = el.hasAttribute('data-height') ? el.getAttribute('data-height')! : `${window.innerHeight - 55}px`;
const width = el.hasAttribute('data-width') ? el.getAttribute('data-width')! : "100%";
const r = ReactDOM.createRoot(el);
const myCache = createEmotionCache({ key: 'stu-grid' });
r.render(
<MantineProvider emotionCache={myCache} withGlobalStyles withNormalizeCSS>
<QueryClientProvider client={queryClient}>
<React.Suspense fallback={<Stack align={'center'} my={25}><Loader variant="dots" size={92} color={'yellow'} /><Text color="dimmed" weight={700}>Loading...</Text></Stack>}>
<GlobalStateProvider>
<App uid={uid!} widgetHeight={height} widgetWidth={width} />
</GlobalStateProvider>
</React.Suspense>
</QueryClientProvider>
</MantineProvider>
);
As you can see in the index.tsx
i am looking for params, my plan is to add iframes and too look for specific params to pull in the right data via API. The most important one to note is uid
everything else will have its own default set. We are also using that id on the element we set in index.html
, and embeding our widget into there.
Grid & Slider Widgets
After configuration its building it out and making it function now and it’s as simple as building the project and putting up on the server and making a simple iframe for it.
Single Widget
Here is where things get a little more interesting. There is extra layer needed here because this is meant as a floating widget This floating widget should only take up where the widget is visible and never the whole screen. We need to utilize Javascript’s Message API so that we can communicate between one website to the other.
First Major Mistake
I made seperate projects for each widget, the fool I am I didn’t realize this issue until after i have completed all of them. Meanwhile i was dealing with the struggle of recreating all Review Widget Cards. This will make future development updates terrible and tedious to work with. This of course could be fixed but now me or whoever will have to deal with the headache I am SORRY! Keeping these 3 widgets together in one repo would’ve been all around better for everyone. 😢
List of mistakes
- Utilize Enviroment Variables more often
- Use Tailwind, a component library was not entirely necessary at all for this and causes too much overhead
- Read documentation
- Create a better development project
- Seperate my components