Hello everyone, really long time no see ……………… Because now summer internship is too busy, basic do not have much time to write their own things

Tragedy… I’ve been wanting to refactor fRE until now, but here’s what this update does:

New time slice

In previous versions, time slicing was mostly done with the help of requestIdleCallback, which had some issues such as poor compatibility (mostly not supported by applets) and uncontrollability (not being able to control the frame rate of slicing and not being able to lose frames), but this API is definitely going to have to be fixed

React time slices are implemented based on requestAnimation + priorities. Ideally, fRe should do the same

const FPS = 1000 / 60

function workLoop (startTime = 0) {
  if (startTime && performance.now() - startTime > FPS) {
    requestAnimationFrame(workLoop)
  } else {
    const nextTime = performance.now()
    nextWork = performWork(nextWork)
    if (nextWork) {
      workLoop(nextTime)
    } else {
      options.commitWork
        ? options.commitWork(pendingCommit)
        : commitWork(pendingCommit)
    }
  }
}
Copy the code

As shown above, fRE also implements a super small schedule based on requestAnimationFrame, which works like this:

  • If a task can be completed in one frame, it can be synchronized to the next task
  • If there are 10 tasks and they can all be completed in one frame, the synchronization process will not be stuck (60fps).
  • If a task cannot be completed in one frame, its next task needs to start in the next frame
  • The task of the next frame is the next slice, which is changed from synchronous to asynchronous to ensure that the complex task does not interfere with the next task

As mentioned above, with just ten lines of code, slicing has good compatibility at the same time, and the process of slicing is also controllable, and the update queue can be sorted according to the priority at any time in the future

Diff algorithm optimization

The react diff doesn’t understand it, and the diFF of other frameworks doesn’t work with Fiber

This optimization is mainly aimed at two cases:

function App () {
  const [arr, setArr] = useState(['A'.'B'.'C'.'D'])
  return (
    <div>
      <ul>
        {arr.map(item => (
          <A key={item} val={item}/>
        ))}
      </ul>
      <button onClick={()= > setArr(['B','A','D','C'])}>+</button>
    </div>
  )
}

function A(props){
  return <div>{props.val}</div>
}
Copy the code

As shown above, this is one of the cases where the key is added to the component, and the key should be transferred to the internal component

On the root element (div), which is why we require components to have an element wrapped around them

If you don’t do this, the key is added to the component, which means it’s not added

{
  isShow && <A />
  isShow ? <A /> : null
  isShow ? <A /> : <B />
}
Copy the code

This is another case. I had been trying to optimize this situation, but found it very difficult. Later I found that I was wrong

This kind of case is difficult to optimize, so the optimization of this part is removed, and the size is reduced to 1.7 KB for the first time in history

It is very difficult to change the position, and the position can only be changed by adding a key

fix bug

Finally understand the useMemo/useCallback/useEffect relationship, the previous implementation has some problems, the new version is removed

UseMemo uses the second parameter to determine if recalculation is required and returns a cached value

UseCallback determines whether to regenerate and returns a cached function reference based on the second argument

UseEffect determines whether the function needs to be executed based on the second argument

To sum up, the new version of FRE logic is more sophisticated, I also according to the agreement, do time slice and scheduling, so far, FRE can be regarded as a small sparrow, all the five organs

Github address: github.com/132yse/fre

Welcome to join us and study the algorithm under Fiber