Redux and Twitter Architecture Patterns in Vanilla JavaScript
Explore two powerful patterns implemented from scratch in plain JavaScript: a Redux-like state management system and a Twitter-inspired social feed engine. These examples give you a deeper understanding of real-world app architecture—without relying on any libraries or frameworks.
Redux Pattern Implementation
An implementation of the Redux pattern using vanilla JavaScript. This custom Store class manages state using a reducer and
supports dispatching actions and subscribing to state changes.
Redux is commonly used for predictable state management in frontend applications like React.
class Store {
constructor(reducer, initialState) {
this.reducer = reducer;
this.state = initialState;
this.listeners = [];
}
getState() {
return this.state;
}
dispatch(action) {
this.state = this.reducer(this.state, action);
this.listeners.forEach((listener) => listener());
}
subscribe(listener) {
this.listeners.push(listener);
return () => {
console.log("unsubscribed");
this.listeners = this.listeners.filter((l) => l !== listener);
};
}
}
// Example reducer function
const reducer = (state, action) => {
switch (action.type) {
case "INCREMENT":
return { ...state, count: state.count + 1 };
case "DECREMENT":
return { ...state, count: state.count - 1 };
default:
return state;
}
};
const initialState = { count: 0 };
const store = new Store(reducer, initialState);
// Subscribe to state changes
const unsubscribe = store.subscribe(() => {
console.log(store.getState());
});
// Dispatch actions
console.log(store.getState());
store.dispatch({ type: "INCREMENT" });
store.dispatch({ type: "INCREMENT" });
store.dispatch({ type: "DECREMENT" });
// Unsubscribe from state changes
unsubscribe();
// { count: 0 }
// { count: 1 }
// { count: 2 }
// { count: 1 }
// unsubscribedTwitter Feed Simulation
A simplified simulation of Twitter’s core features using JavaScript classes. Implements functionality for posting tweets, following/unfollowing users, and generating personalized news feed.
Key features:
postTweet(userId, tweetId)– Posts a tweet for a user.follow(followerId, followeeId)– Allows one user to follow another.unfollow(followerId, followeeId)– Allows a user to unfollow someone (except themselves).getNewsFeed(userId)– Returns the 10 most recent tweets from the user and users they follow.
Demonstrates how to work with Map, Set, arrays, and sorting for feed generation.
class Twitter {
constructor() {
this.follows = new Map();
this.tweets = new Map();
this.timestamp = 0;
}
postTweet(userId, tweetId) {
if (!this.tweets.has(userId)) {
this.tweets.set(userId, []);
}
this.tweets.get(userId).unshift({ tweetId, timestamp: this.timestamp++ });
if (!this.follows.has(userId)) {
this.follows.set(userId, new Set());
// User follows themselves
this.follows.get(userId).add(userId);
}
}
getNewsFeed(userId) {
if (!this.follows.has(userId)) return [];
const followed = this.follows.get(userId);
const feed = [];
for (const followeeId of followed) {
if (this.tweets.has(followeeId)) {
feed.push(...this.tweets.get(followeeId));
}
}
feed.sort((a, b) => b.timestamp - a.timestamp);
return feed.map((tweet) => tweet.tweetId);
}
follow(followerId, followeeId) {
if (!this.follows.has(followerId)) {
this.follows.set(followerId, new Set());
// User follows themselves
this.follows.get(followerId).add(followerId);
}
this.follows.get(followerId).add(followeeId);
}
unfollow(followerId, followeeId) {
// Cannot unfollow oneself
if (followerId === followeeId) return;
if (this.follows.has(followerId)) {
this.follows.get(followerId).delete(followeeId);
}
}
}
const twitter = new Twitter();
// User 1 posts a tweet with ID 5
twitter.postTweet(1, 5);
// User 1 retrieves their news feed (should contain only tweet 5)
console.log(twitter.getNewsFeed(1)); // [5]
// User 1 follows User 2
twitter.follow(1, 2);
// User 2 posts a tweet with ID 6
twitter.postTweet(2, 6);
// User 1 retrieves their news feed (should contain tweets 6 and 5, most recent first)
console.log(twitter.getNewsFeed(1)); // [6, 5]
// User 1 unfollows User 2
twitter.unfollow(1, 2);
// User 1 retrieves their news feed (should only contain their own tweet, 5)
console.log(twitter.getNewsFeed(1)); // [5]