React: Difference between revisions

Jump to navigation Jump to search
Line 1,180: Line 1,180:
// object[first] = "Deacon"
// object[first] = "Deacon"


</source>
=== Composition ===
chaining
<source lang="js">
const template = "hh:mm:ss tt";
const clockTime = template
  .replace("hh", "03")
  .replace("mm", "33")
  .replace("ss", "33")
  .replace("tt", "PM");
console.log(clockTime);
// "03:33:33 PM"
</source>
<code>both</code> function pipes a value through two separate functions.
<source lang="js">
const both = date => appendAMPM(civilianHours(date));
// but hard to read, so better approach is to use higher order function
const compose = (...fns) => arg =>
  fns.reduce((composed, f) => f(composed), arg);
const both = compose(
  civilianHours,
  appendAMPM
);
both(new Date());
</source>
== Putting it all together ==
ticking time
<source lang="js">
// Log Clock Time every Second
setInterval(logClockTime, 1000);
function logClockTime() {
  // Get Time string as civilian time
  let time = getClockTime();
  // Clear the Console and log the time
  console.clear();
  console.log(time);
}
function getClockTime() {
  // Get the Current Time
  let date = new Date();
  let time = "";
  // Serialize clock time
  let time = {
    hours: date.getHours(),
    minutes: date.getMinutes(),
    seconds: date.getSeconds(),
    ampm: "AM"
  };
  // Convert to civilian time
  if (time.hours == 12) {
    time.ampm = "PM";
  } else if (time.hours > 12) {
    time.ampm = "PM";
    time.hours -= 12;
  }
  // Prepend a 0 on the hours to make double digits
  if (time.hours < 10) {
    time.hours = "0" + time.hours;
  }
  // prepend a 0 on the minutes to make double digits
  if (time.minutes < 10) {
    time.minutes = "0" + time.minutes;
  }
  // prepend a 0 on the seconds to make double digits
  if (time.seconds < 10) {
    time.seconds = "0" + time.seconds;
  }
  // Format the clock time as a string "hh:mm:ss tt"
  return time.hours + ":" + time.minutes + ":" + time.seconds + " " + time.ampm;
}
</source>
REFACTORING using what we learned
in functional programs, use functions over values wherever possible; invoke the function to obtain the value when needed
<source lang="js">
const oneSecond = () => 1000;
const getCurrentTime = () => new Date();
const clear = () => console.clear();
const log = message => console.log(message);
</source>
three functions will be used to mutate the clock
# serializeClockTime - take a date object and returns a object for clock time that contains hours minutes, and seconds.
# civilianHours - takes the clock time object and returns an object where hours are converted to civilian time (1300 becomes 1:00)
# appendAMPM - take the clock time object and appends time of day, AM or PM, to that object.
<source lang="js">
const serializeClockTime = date => ({
  hours: date.getHours(),
  minutes: date.getMinutes(),
  seconds: date.getSeconds()
});
const civilianHours = clockTime => ({
  ...clockTime,
  hours: clockTime.hours > 12 ? clockTime.hours - 12 : clockTime.hours
});
const appendAMPM = clockTime => ({
  ...clockTime,
  ampm: clockTime.hours >= 12 ? "PM" : "AM"
});
</source>
higher order functions needed
# display - takes a target function and returns a function that will send a time to the target. In this eample the target will be console.log
# formatClock - takes a template string and uses it to return clock time formatted based upon the criteria from the string.
# prependZero -
<source lang="js">
const display = target => time => target(time);
const formatClock = format => time =>
  format
    .replace("hh", time.hours)
    .replace("mm", time.minutes)
    .replace("ss", time.seconds)
    .replace("tt", time.ampm);
const prependZero = key => clockTime => ({
  ...clockTime,
  [key]: clockTime[key] < 10 ? "0" + clockTime[key] : clockTime[key]
});
</source>
compose
<source lang="js">
const convertToCivilianTime = clockTime =>
  compose(
    appendAMPM,
    civilianHours
  )(clockTime);
const doubleDigits = civilianTime =>
  compose(
    prependZero("hours"),
    prependZero("minutes"),
    prependZero("seconds")
  )(civilianTime);
const startTicking = () =>
  setInterval(
    compose(
      clear,
      getCurrentTime,
      serializeClockTime,
      convertToCivilianTime,
      doubleDigits,
      formatClock("hh:mm:ss tt"),
      display(log)
    ),
    oneSecond()
  );
startTicking();
</source>
</source>