首页 > 解决方案 > 递归在 React 中的工作很奇怪

问题描述

我正在尝试使用 React 创建Head Recursion的可视化,但代码在这里工作得很奇怪。使用尾递归,行为与预期一致,但使用头递归,它超越了递归调用并从下到上打印数字,但最先打印底部的数字。(尝试使用 setState 进行延迟打印。)以下是相同的代码。

import React from 'react'

const Box = (props) => {
    const [loading, setLoading] = React.useState(true)
    var n = props.num
    // setTimeout(() => {
    //     setLoading(false)
    // }, 1000)

    // if (loading) {
    //     return <h1></h1>
    // }

    return (
        <div style={{
            marginLeft: n * 40,
            marginTop: 40
        }}>
            {n > 0 ? <> <Box num={n - 1} /> {console.log(`Called with n = ${n}`)} <div style={{
                width: 300,
                display: 'flex',
                flexDirection: 'row',
                alignItems: 'center',
                justifyContent: 'space-evenly',
                border: '1px solid black'
            }}>
                <h1>{n}</h1>
                <h1>fun({n - 1})</h1>
            </div>
            </> : null}
        </div>
    )
}

export default Box

执行时,console.log( Called with n = ${n})会在以 n-1 递归调用 Box 后立即被调用。(我猜这不应该发生,因为它应该完成递归调用,然后它应该控制台记录值以相反的方式记录)。我用 n = 5 调用该组件。谁能解释一下这里有什么问题。提前致谢。

标签: reactjsrecursion

解决方案


你可以看到你的 JSX 转化为 babel 的站点的 JS ,(这是浏览器实际执行的)。

对于您的组件,它变成了这样,

import React from 'react';

const Box = props => {
  const [loading, setLoading] = React.useState(true);
  var n = props.num; // setTimeout(() => {
  //     setLoading(false)
  // }, 1000)
  // if (loading) {
  //     return <h1></h1>
  // }

  return React.createElement("div", {
    style: {
      marginLeft: n * 40,
      marginTop: 40
    }
  }, n > 0 ? React.createElement(React.Fragment, null, " ", React.createElement(Box, {
    num: n - 1
  }), " ", console.log(`Called with n = ${n}`), " ", React.createElement("div", {
    style: {
      width: 300,
      display: 'flex',
      flexDirection: 'row',
      alignItems: 'center',
      justifyContent: 'space-evenly',
      border: '1px solid black'
    }
  }, React.createElement("h1", null, n), React.createElement("h1", null, "fun(", n - 1, ")"))) : null);
};

export default Box;

看这个你可以看到console.log被调用并且返回值被传递给React.CreateElementconsole.log递归调用之前发生的事情,这就是你看到日志从n = 5到n = 1的原因。


推荐阅读