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 }
// unsubscribed
Twitter 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]