Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions customRedux/createStore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
const createStore = (reducer, preloadedState) => {
if (typeof reducer !== "function") {
throw new Error("Reducer must be a function");
}

let state = preloadedState;
let isDispatching = false;
const listeners = [];

// returns the current state
const getState = () => {
if (isDispatching) {
throw new Error("Cannot call store.getState while dispatching");
}

return state;
};

// it is used to watch store changes. Listeners are invoked whenever an action is dispatched
const subscribe = (listener) => {
if (typeof listener !== "function") {
throw new Error("Store listeners should be of type function");
}

if (isDispatching) {
throw new Error("Cannot call store.subscribe while dispatching");
}

listeners.push(listener);

return function unsubscribe() {
if (isDispatching) {
throw new Error("Cannot call store.unsubscribe while dispatching");
}

const index = listeners.indexOf(listener);
listeners.splice(index, 1);
};
};

// it is used to trigger store changes, dispatch actions
const dispatch = (action) => {
if (typeof action !== "object") {
throw new Error("An action should be a plain object");
}

if (typeof action.type === "undefined") {
throw new Error("Action should have a type");
}

if (isDispatching) {
throw new Error("Cannot call store.dispatch while dispatching");
}

/**
* { type: 'ADD_VIDEO', payload: {...} }
*
* {
* videos: { data: [] } --> videos()
* users: { data: [] } --> users()
* }
*
* videos(state, { type: 'ADD_VIDEO', payload })
* users(state, { type: 'ADD_VIDEO', payload })
*
* (state, action) => {
* videos,
* users
* }
*/

isDispatching = true;

try {
state = reducer(state, action);
} finally {
isDispatching = false;
}

listeners.forEach((listener) => listener());

return action;
};

dispatch({
type: "INIT_ACTION",
});

return {
getState,
subscribe,
dispatch,
};
};

module.exports = createStore;
5 changes: 5 additions & 0 deletions customRedux/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const createStore = require("./createStore");

module.exports = {
createStore,
};
62 changes: 62 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const { combineReducers } = require("redux");
const { createStore } = require("./customRedux/index");
const videos = require("./reducers/videos");
const users = require("./reducers/users");

const initialState = {
videos: {
data: [
{
id: 1,
title: "Flat Array Interview Question",
link: "https://bit.ly/devtools-afiq",
},
],
},
};

const rootReducer = combineReducers({
videos,
users,
});

// createStore(reducer, preloadedState, enhancer)
const store = createStore(rootReducer, initialState);
/**
* {
* getState,
* subscribe,
* dispatch
* }
*/

// to check the initial value of our store
console.log("------ INITIAL CALL ------\n", store.getState());

// to watch store changes
store.subscribe(() => {
console.log("Listener called");
});

// to trigger store changes
store.dispatch({
type: "ADD_VIDEO",
payload: {
id: 2,
title: "DOM API Interview Question",
link: "https://bit.ly/devtools-daiq",
},
});

console.log("------ SECOND CALL ------\n", store.getState());

store.dispatch({
type: "ADD_VIDEO",
payload: {
id: 3,
title: "Build Your Own Redux",
link: "https://bit.ly/devtools-byor",
},
});

console.log("------ LAST CALL ------\n", store.getState());
22 changes: 22 additions & 0 deletions reducers/users.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const USER_ACTIONS = {
ADD_USER: "ADD_USER",
};

function users(
state = {
data: [],
},
action
) {
switch (action.type) {
case USER_ACTIONS.ADD_USER:
return {
...state,
data: [...state.data, action.payload],
};
default:
return state;
}
}

module.exports = users;
22 changes: 22 additions & 0 deletions reducers/videos.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const VIDEOS_ACTIONS = {
ADD_VIDEO: "ADD_VIDEO",
};

function videos(
state = {
data: [],
},
action
) {
switch (action.type) {
case VIDEOS_ACTIONS.ADD_VIDEO:
return {
...state,
data: [...state.data, action.payload],
};
default:
return state;
}
}

module.exports = videos;