Sunday, January 30, 2022

CSS flex usage note

Flex can be used to solve most ui layout requirements in regular business applications if each items need to have equal height. 

Flex consists of flex container and flex items, each of them supports different css styles. It is important to understand which css style works on flex container or flex items.

Flex container:

For any container html element, when setting the below css style to it, the element becomes a flex container, and any direct sub elements become flex items.

.myform {

  display: flex;

}

The flex container has the below css styles:

.myform {

  display: flex;

  flex-wrap: wrap;  //control whether wrap the elements when page shrinks

 justify-content: center; // control where to shall all flex item in flex container in main axis: center, flex-start, flex-end, space-around, space-between

align-items: stretch; // control how each flex item is aligned in cross axis direction: stretch, flex-start, flex-end, center and baseline

align-content: normal: //control how all flex items are align in flex container in cross axis direction, not used very often.

}


Flex elements

Any direct sub elements of flex container element can be styled by flex item css styles. The styles controls the element itself and its sibling elements' behavior. The styles include:

flex: define how the element will grow or shrink when the page width changes. It can be used to define how item grows and shrinks related to other elements. For example, a growing input text box with a button with default width can be defined as below

   input[type="text"] {

      flex: 1 0 auto

  }

  button[type="submit"] {

    flex: initial 0 initial

  }


Sample usage 1

A growing field and a fix width item, the growing field occupies all remaining line

  .search-form {
    display: flex;
    flex-wrap: wrap;
  }
  growingitem {
    flex: 1 0 auto
  }
 fixeditem {
    flex: initial 0 initial
  }


Sample usage 2

Two fields occupy left and right end of the line by setting justify-content: space-between

  .search-form {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
  }
  input[type="search"] {
    flex: 1 0 initial
  }
  button[type="submit"] {
    flex: 1 0 initial
  }

Expanding item to occupy all its container's space 
When setting the below display style to any item within a container, the item becomes a flex container, and by default, flex container will expend and stretch to all available space in container.  
display: flex

Thursday, January 27, 2022

Difference between React useCallback and useMemo

React useCallback and useMemo hooks look similar, and both of them take a callback function, and dependent array as parameters. But their returns different values to the callers.

useCallback hook returns a memorized callback function, if the dependencies are changed. So the type of the variable assigned by useCallback is a function object. The function object itself is memorized, so when rendering the parent react function component, the function object will not be created again and again as new function objects. The function object body will not be invoked until in the project someone calls the function.

useMemo hook returns a memorized object, so the type of the variable assigned by useMemo may be any type depends what is returned from the callback method body in useMemo's first parameter. If nothing is returned, then the variable assigned by useMemo hook is undefined. Different from useCallback hook, when assigning a variable by useMemo hook, the callback method of useMemo hook will be called immediately, no matter whether the variable is used or not by the application. 

Since both useMemo and useEffect will automatically execute their callback method when page loads or when dependency parameters change, so their functions look similar. But useMemo is executed during DOM rendering. while use Effect is executed after DOM rendering, for the time consuming operation such as remote network requests. 

In practice, it is important in many times, the cost of using useCallback and useMemo may be bigger than the benefit bringing by it, and requirement of setting the proper dependent array parameter may introduce new bugs to the logic, so they should be used with caution in the real project.

Set dependent array parameter in useCallback (and other react) hooks

React callback hook creates memorized callback function, the memorized callback function gets created once, but will be invoked later for many times. If the callback function uses any values returned by useState() hook, then those values must be included in the useCallback's dependent array parameter. The reason is when useCallback is created, it captures all the closure variables as a snapshot for future usage. After that, if some values are updated by calling set method of useState() hook, the updated values will be not reflected in the closure snapshot captured by useCallback hook when it was created, so when the callback hook method is called after its creating, it will still use the original out-of-date values it captured when it was created. 

So as a simple rule, when defining hooks with dependent parameters, always including all values controlled by useState() in its dependent parameter.