Reactjs React路由器组件呈现非常错误的状态 import React,{useffect,useState}来自“React” 从“react router dom”导入{Route} 从“react Router dom”导入{BrowserRouter as Router} 导出默认函数测试(){ 常数s=使用() 如果(s=='aa'){ 返回空 } 返回( ) } 函数MyCpt(){ 常数s=使用() 返回{s} } 函数useS(){ const[state,setState]=useState('aa') useffect(()=>{ 订阅(设置状态) }, []) 返回状态 } 常量侦听器=[] 功能订阅(cb){ listeners.push(cb) } 设置超时(()=>{ listeners.forEach((cb)=>{ cb('bb') }) }, 2000)

Reactjs React路由器组件呈现非常错误的状态 import React,{useffect,useState}来自“React” 从“react router dom”导入{Route} 从“react Router dom”导入{BrowserRouter as Router} 导出默认函数测试(){ 常数s=使用() 如果(s=='aa'){ 返回空 } 返回( ) } 函数MyCpt(){ 常数s=使用() 返回{s} } 函数useS(){ const[state,setState]=useState('aa') useffect(()=>{ 订阅(设置状态) }, []) 返回状态 } 常量侦听器=[] 功能订阅(cb){ listeners.push(cb) } 设置超时(()=>{ listeners.forEach((cb)=>{ cb('bb') }) }, 2000),reactjs,react-router-v4,Reactjs,React Router V4,这里是完全可运行的代码,简单但有线。如您所见,MyCpt将呈现useS的状态,最终将是bb(2秒后)。但是,无论您等待多长时间,它都将呈现aa。如果在if(s==='aa')中注释掉returnnull,它将按预期呈现bb 黑客正在发生什么?如果您使用一些日志(下面的代码),就会很清楚。查看控制台.log: import React, { useEffect, useState } from 'react' import { Route } from 'react-router-dom' imp

这里是完全可运行的代码,简单但有线。如您所见,
MyCpt
将呈现
useS
的状态,最终将是
bb
(2秒后)。但是,无论您等待多长时间,它都将呈现
aa
。如果在
if(s==='aa')
中注释掉
returnnull
,它将按预期呈现
bb

黑客正在发生什么?

如果您使用一些日志(下面的代码),就会很清楚。查看
控制台.log

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)
步骤1-2)首先记录“Test aa”,并且在钩子内部进行订阅,但是由于返回null,组件退出

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

步骤5-6)现在,
MyCpt
正在运行,订阅发生,但监听器不再被调用


下面是日志代码:

1. Test aa 
2. Subscribed 
3. Running listeners 1 
4. Test bb 
5. MyCpt aa 
6. Subscribed 
import React,{useffect,useState}来自“React”;
从“react router dom”导入{Route};
从“react Router dom”导入{BrowserRouter as Router};
导出默认函数测试(){
常数s=使用();
控制台日志(“测试”,s);
如果(s==“aa”){
返回null;
}
返回(
);
}
函数MyCpt(){
常数s=使用();
console.log(“MyCpt”,s);
返回{s};
}
函数useS(){
常量[状态,设置状态]=使用状态(“aa”);
useffect(()=>{
认购(设定状态);
}, []);
返回状态;
}
常量侦听器=[];
功能订阅(cb){
控制台日志(“订阅”);
推送(cb);
}
设置超时(()=>{
log(“Running listeners”,JSON.stringify(listeners.length));
listeners.forEach((cb)=>{
cb(“bb”);
});
}, 2000);

我的问题实际上是从一个现实世界的复杂项目中抽象出来的,你的回答指出了正确的方向
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);