Skip to content

Instantly share code, notes, and snippets.

@mondwan
Last active March 19, 2017 16:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mondwan/f5b93044b9e86f6bad34ad213face203 to your computer and use it in GitHub Desktop.
Save mondwan/f5b93044b9e86f6bad34ad213face203 to your computer and use it in GitHub Desktop.
Knowledge digested from react-basic

Source

https://github.com/reactjs/react-basic/blob/master/README.md

function NameBox(name) {
  return { fontWeight: 'bold', labelContent: name };
}

// Level 1 reuse: Show user name with blue border
function FancyUserBox(user) {
  return {
    borderStyle: '1px solid blue',
    childContent: [
      'Name: ',
      NameBox(user.firstName + ' ' + user.lastName)
    ]
  };
}

// Level 2 reuse: Create an abstraction about a bordered box with any children
function FancyBox(children) {
  return {
    borderStyle: '1px solid blue',
    children: children
  };
}

// A concret implementation for a UserBox show user's name with blue border provided by fancy box
function UserBox(user) {
  return FancyBox([
    'Name: ',
    NameBox(user.firstName + ' ' + user.lastName)
  ]);
}

// Introduce state with react component
// Superior version of UserBox with like count and like button
function FancyNameBox(user, likes, onClick) {
  return FancyBox([
    'Name: ', NameBox(user.firstName + ' ' + user.lastName),
    'Likes: ', LikeBox(likes),
    LikeButton(onClick)
  ]);
}

// Implementation Details

var likes = 0;
function addOneMoreLike() {
  likes++;
  rerender();
}

// Init

FancyNameBox(
  { firstName: 'Sebastian', lastName: 'Markbage' },
  likes,
  addOneMoreLike
);

// Memoization => Avoid wasting resources on same computations if function is pure at first
function memoize(fn) {
  var cachedArg;
  var cachedResult;
  return function(arg) {
    if (cachedArg === arg) {
      return cachedResult;
    }
    cachedArg = arg;
    cachedResult = fn(arg);
    return cachedResult;
  };
}

// Return the same name box with same argument => Avoid useless computations
var MemoizedNameBox = memoize(NameBox);

// A variant of FancyBox with Name box plus Age
function NameAndAgeBox(user, currentTime) {
  return FancyBox([
    'Name: ',
    MemoizedNameBox(user.firstName + ' ' + user.lastName),
    'Age in milliseconds: ',
    currentTime - user.dateOfBirth
  ]);
}

// Introduce concept of list

// Create a list of FancyNameBox with a list of user's data and a map of like count with user id
function UserList(users, likesPerUser, updateUserLikes) {
  return users.map(user => FancyNameBox(
    user,
    likesPerUser.get(user.id),
    // Defer the updateUserLikes with sufficient data for computation => wraps itself as on Click
    () => updateUserLikes(user.id, likesPerUser.get(user.id) + 1)
  ));
}

var likesPerUser = new Map();
function updateUserLikes(id, likeCount) {
  likesPerUser.set(id, likeCount);
  rerender();
}

UserList(data.users, likesPerUser, updateUserLikes);

// No memorization at this point as it can memorize one value at a time

// Continuations

// Defer the concret instantiation of user list => fancy user list
function FancyUserList(users) {
  return FancyBox(
    UserList.bind(null, users)
  );
}

// Defer the instantiation of UserList such that likes and callback can provided later on
const box = FancyUserList(data.users);
// Instantiate UserList (finally) by providing like counts and callback
const resolvedChildren = box.children(likesPerUser, updateUserLikes);
// Final FancyBox with user list
const resolvedBox = {
  ...box,
  children: resolvedChildren
};

// TODO: State map, Memorization map, Algebraic Effects
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment