Можно ли использовать useMemo для поиска чисел Фибоначчи на странице React? - PullRequest
1 голос
/ 20 февраля 2020

Это занимает более 30 секунд (вместо 1 секунды), поэтому я не думаю, что он правильно использует useMemo:

<body>

    <script src="https://unpkg.com/react@16.12.0/umd/react.development.js" crossorigin></script>
    <script src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js" crossorigin></script>
    <script src="https://unpkg.com/@babel/standalone@7.8.4/babel.min.js" crossorigin></script>

    <div id="root"></div>

    <script type="text/babel">

        function Fib({n}) {
            const m = Number(n)
            console.log("Fib", m);

            const fib = (n) => {
                if (n <= 1) return n;
                else return fib(n-1) + fib(n-2);
            }
            
            const result = React.useMemo(() => fib(m), [m]);

            return <li key={m}>Fibonacci({m}) is {result}</li>;

        }

        function App() {
            return (
                <ul>
                    { Array.from({length: 41}).map((e,i) => 
                        <Fib key={i} n={i} />
                    )}
                </ul>
            )
        }

        ReactDOM.render(<App />, document.querySelector("#root"));

    </script>
</body>

Кажется, на самом деле это должно быть:

const fib = (n) => {
    if (n <= 1) return n;
    else return React.useMemo(() => fib(m - 1), [m - 1]) + React.useMemo(() => fib(m - 2), [m - 2]);
}

const result = React.useMemo(() => fib(m), [m]);

, но useMemo() должен использоваться в функции "верхнего уровня". Можно ли заставить его работать?

1 Ответ

0 голосов
/ 21 февраля 2020

Я не верю, что возможно использовать useMemo() в рекурсивной функции fib() из-за правил React размещения хуков (как вы упомянули).

Если вы включите fib() в пользовательский хук Правила React могут быть удовлетворены, но он взорвал стек - в этот момент я отдал его.
По существу, существует конфликт между выражением для завершения рекурсии if (n <= 1) и правилом React, которое говорит, что хуки должны условно не вызываться.

Если вы переместите fib() за пределы компонента Fib, вы сократите время пополам (грубый подсчет). Это связано с тем, что функция не создается заново при каждом вызове,

Использование памятки подчеркивания позволяет получить значение, близкое к ожидаемому.

<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js" integrity="sha256-G7A4JrJjJlFqP0yamznwPjAApIKPkadeHfyIwiaa9e0=" crossorigin="anonymous"></script>
<script src="https://unpkg.com/react@16.12.0/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16.12.0/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/@babel/standalone@7.8.4/babel.min.js" crossorigin></script>
<script src="https://unpkg.com/@babel/standalone@7.8.4/babel.min.js" crossorigin></script>
<body>
    <div id="root"></div>

    <script type="text/babel">

      const fib = _.memoize(function(n) {
        return (n <= 1) ? n : fib(n-1) + fib(n-2);
      });

      function Fib({n}) {
        const result = React.useMemo(() => fib(n), [n]);
        return (
          <li key={n}>Fibonacci({n}) is {result}</li>
        )
      }

      function App() {
        return (
          <ul>
            { Array.from({length: 41}).map((e,i) => 
              <Fib key={i} n={i} />
            )}
          </ul>
        )
      }

      ReactDOM.render(<App />, document.querySelector("#root"));

    </script>
</body>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...