React路由器组件呈现非常错误的状态

问题描述

import React,{ useEffect,useState } from 'react'
import { Route } from 'react-router-dom'
import { browserRouter as Router } from 'react-router-dom'

export default function test() {
  const s = useS()
  if (s === 'aa') {
    return null
  }
  return (
    <Router>
      <Route component={MyCpt}></Route>
    </Router>
  )
}

function MyCpt() {
  const s = useS()
  return <h1>{s}</h1>
}

function useS() {
  const [state,setState] = useState('aa')
  useEffect(() => {
    subscribe(setState)
  },[])
  return state
}

const listeners = []
function subscribe(cb) {
  listeners.push(cb)
}

setTimeout(() => {
  listeners.forEach((cb) => {
    cb('bb')
  })
},2000)

这里是完全可运行的代码,只需连接即可。如您所见,MyCpt将从useS渲染状态,最终将为bb(2秒后)。但是,无论您等待多长时间,它都会呈现aa。如果您在return null内将if (s === 'aa')注释掉,它将按预期呈现bb

黑客正在发生什么?

解决方法

如果您使用一些日志(下面的代码),它将很清楚。查看console.log

1. Test aa 
2. Subscribed 
3. Running listeners 1 
4. Test bb 
5. MyCpt aa 
6. Subscribed 

步骤1-2)会发生什么情况,首先记录“ Test aa”,并且在挂钩内进行订阅,但是由于返回null,因此该组件退出了。

步骤3-4)之后,运行已注册的侦听器(请注意,到目前为止仅注册了一个侦听器,请参阅计数1 ),因此输出“正在运行的侦听器1”从组件Test中打印出“测试bb”。

步骤5-6)现在,MyCpt正在运行,并且发生了订阅,但是没有再次调用侦听器。


以下是带有日志的代码:

import React,{ useEffect,useState } from "react";
import { Route } from "react-router-dom";
import { BrowserRouter as Router } from "react-router-dom";

export default function Test() {
  const s = useS();
  console.log("Test",s);
  if (s === "aa") {
    return null;
  }
  return (
    <Router>
      <Route component={MyCpt}></Route>
    </Router>
  );
}

function MyCpt() {
  const s = useS();
  console.log("MyCpt",s);

  return <h1>{s}</h1>;
}

function useS() {
  const [state,setState] = useState("aa");
  useEffect(() => {
    subscribe(setState);
  },[]);
  return state;
}

const listeners = [];
function subscribe(cb) {
  console.log("Subscribed");
  listeners.push(cb);
}

setTimeout(() => {
  console.log("Running listeners",JSON.stringify(listeners.length));
  listeners.forEach((cb) => {
    cb("bb");
  });
},2000);

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...