3. 解决 edge case 的方式

0 阅读1分钟

本次课程我们来处理一个edge case. 代码如下,现在运行会报错。

import React from './core/React.js';
​
let showBar = false
 
function Counter({ num }) {
  const bar = <div>bar</div>
​
​
  function handleShowBar() {
    showBar = !showBar
    React.update()
  }
​
  return <div>
    Counter
    <button onClick={handleShowBar}>showBar</button>
    {showBar && bar}
  </div>
}
​
function App() {
  return <div>
    hi-mini-react
    <Counter></Counter>
  </div>
}
export default App; 

1.png

尝试定位问题

function createElement(type, props, ...children) {
    return {
        type,
        props: {
            ...props,
            children: children.map(child => {
                console.log('child 111', child)
                const isTextNode = typeof child === "string" || typeof child === "number"
                return isTextNode ? createTextNode(child) : child
            })
        }
    }
}
  • 打印一下child,出现false,找到了问题点,false不是textNode也不是对象节点

3.png

  • 额外处理,false的情况,reconcileChildren增加if (child) {
function reconcileChildren(fiber, children) {
    let oldFiber = fiber.alternate?.child
    let prevChild = null
    children.forEach((child, index) => {
        const isSameType = oldFiber && oldFiber.type === child.type
        let newFiber
        if (isSameType) {
            //update
            newFiber = {
                type: child.type,
                props: child.props,
                child: null,
                parent: fiber,
                sibling: null,
                dom: oldFiber.dom,
                effectTag: "update",
                alternate: oldFiber
            }
        } else {
            if (child) {
                newFiber = {
                    type: child.type,
                    props: child.props,
                    child: null, 
                    parent: fiber,
                    sibling: null,
                    dom: null,
                    effectTag: "placement"
                }
            }
​
            if (oldFiber) {
                deletions.push(oldFiber)
            }
        }
​
        if (oldFiber) {
            oldFiber = oldFiber.sibling
        }
​
        if (index === 0) {
            fiber.child = newFiber
        } else {
            prevChild.sibling = newFiber
        }
        prevChild = newFiber
    })
    while (oldFiber) {
        deletions.push(oldFiber)
        oldFiber = oldFiber.sibling
    }
}

4.png

  • 可以正常切换

新的问题,修改app中的位置

  return <div>
    Counter
    {showBar && bar}
    <button onClick={handleShowBar}>showBar</button>
  </div>
  • 报错了

5.png

  • 处理button的时候拿之前的节点拿不到

6.png

  • 赋值增加判断
function reconcileChildren(fiber, children) {
        if (newFiber) {
            prevChild = newFiber
        }
    })