ReactJS Program to Toast Queue Reducer with Explanation
ReactJS
Hard
State Management
23 views
1 min read
86 words
This problem helps you practice core ReactJS fundamentals in a practical way. It builds intuition around toast, react, queue. Let’s break it down step by step so you can implement it confidently.
Problem Statement
Build a toast system where new messages appear and auto-dismiss.
Input Format
No input.
Output Format
Render a React component.
Constraints
Use useReducer and remove items after a timeout.
Code Solution
This explanation is written for learning purposes and to help beginners understand the concept clearly.
import React, { useEffect, useReducer, useRef, useState } from 'react';
function reducer(state, action) {
if (action.type === 'add') return [{ id: action.id, text: action.text }, ...state];
if (action.type === 'remove') return state.filter((t) => t.id !== action.id);
return state;
}
export default function App() {
const [toasts, dispatch] = useReducer(reducer, []);
const [text, setText] = useState('Saved to meetcode');
const timers = useRef(new Map());
useEffect(() => {
return () => {
for (const id of timers.current.values()) clearTimeout(id);
timers.current.clear();
};
}, []);
function addToast() {
const t = text.trim();
if (!t) return;
const id = Date.now().toString(36) + Math.random().toString(36).slice(2);
dispatch({ type: 'add', id, text: t });
const timerId = setTimeout(() => {
dispatch({ type: 'remove', id });
timers.current.delete(id);
}, 2400);
timers.current.set(id, timerId);
}
return (
<div style={{ padding: 16 }}>
<h2 style={{ marginTop: 0 }}>meetcode toasts</h2>
<div style={{ display: 'flex', gap: 10 }}>
<input value={text} onChange={(e) => setText(e.target.value)} style={{ flex: 1, padding: '10px 12px', borderRadius: 12, border: '1px solid #bbb' }} />
<button type='button' onClick={addToast} style={{ padding: '10px 14px', borderRadius: 12, border: 0, background: '#0b5', color: '#fff' }}>Show</button>
</div>
<div style={{ position: 'fixed', right: 16, top: 16, display: 'grid', gap: 10, width: 280 }}>
{toasts.map((t) => (
<div key={t.id} style={{ border: '1px solid #eee', background: '#fff', borderRadius: 14, padding: 12, boxShadow: '0 6px 20px rgba(0,0,0,0.08)' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 10 }}>
<div style={{ color: '#124', fontWeight: 700 }}>{t.text}</div>
<button type='button' onClick={() => dispatch({ type: 'remove', id: t.id })} style={{ border: 0, background: 'transparent', fontSize: 16, lineHeight: 1 }} aria-label='Dismiss'>×</button>
</div>
</div>
))}
</div>
</div>
);
}
Output Example
No sample I/O is provided for this question.
Common Mistakes
- Misreading input/output format.
- Not handling constraints and edge cases.
- Off-by-one errors in loops.
- Forgetting to reset variables between test cases (if any).
Solution Guide
Problem
Build a toast system where new messages appear and auto-dismiss.
Input / Output
Output
Render a React component.
Constraints
Use useReducer and remove items after a timeout.
Details
Common Mistakes
- Misreading input/output format.
- Not handling constraints and edge cases.
- Off-by-one errors in loops.
- Forgetting to reset variables between test cases (if any).
Official Solution
import React, { useEffect, useReducer, useRef, useState } from 'react';
function reducer(state, action) {
if (action.type === 'add') return [{ id: action.id, text: action.text }, ...state];
if (action.type === 'remove') return state.filter((t) => t.id !== action.id);
return state;
}
export default function App() {
const [toasts, dispatch] = useReducer(reducer, []);
const [text, setText] = useState('Saved to meetcode');
const timers = useRef(new Map());
useEffect(() => {
return () => {
for (const id of timers.current.values()) clearTimeout(id);
timers.current.clear();
};
}, []);
function addToast() {
const t = text.trim();
if (!t) return;
const id = Date.now().toString(36) + Math.random().toString(36).slice(2);
dispatch({ type: 'add', id, text: t });
const timerId = setTimeout(() => {
dispatch({ type: 'remove', id });
timers.current.delete(id);
}, 2400);
timers.current.set(id, timerId);
}
return (
<div style={{ padding: 16 }}>
<h2 style={{ marginTop: 0 }}>meetcode toasts</h2>
<div style={{ display: 'flex', gap: 10 }}>
<input value={text} onChange={(e) => setText(e.target.value)} style={{ flex: 1, padding: '10px 12px', borderRadius: 12, border: '1px solid #bbb' }} />
<button type='button' onClick={addToast} style={{ padding: '10px 14px', borderRadius: 12, border: 0, background: '#0b5', color: '#fff' }}>Show</button>
</div>
<div style={{ position: 'fixed', right: 16, top: 16, display: 'grid', gap: 10, width: 280 }}>
{toasts.map((t) => (
<div key={t.id} style={{ border: '1px solid #eee', background: '#fff', borderRadius: 14, padding: 12, boxShadow: '0 6px 20px rgba(0,0,0,0.08)' }}>
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 10 }}>
<div style={{ color: '#124', fontWeight: 700 }}>{t.text}</div>
<button type='button' onClick={() => dispatch({ type: 'remove', id: t.id })} style={{ border: 0, background: 'transparent', fontSize: 16, lineHeight: 1 }} aria-label='Dismiss'>×</button>
</div>
</div>
))}
</div>
</div>
);
}
Solutions (0)
No solutions submitted yet. Be the first!