【问题标题】:React conditional re-rendering not working using functional component使用功能组件反应条件重新渲染不起作用
【发布时间】:2021-10-27 02:31:20
【问题描述】:

有人可以解释为什么“条件”在收到响应并设置状态时更改时不会触发重新渲染?

运行此代码时,即使响应为真,它也始终重定向到“/unauthorized/login”。我认为当状态改变时页面总是会重新渲染。

const PrivateRoute = props => {
const [condition, setCondition] = useState('');

useEffect(() => {
    if (!condition) {
        getUserAccess();
    }
}, [condition]);

const getUserAccess = async () => {
    const response = await axios.get("/some-api");
    const status = response.data; /* status will either be true or false */
    setCondition(status);
}

return condition ? (<Route path={props.path} exact={props.exact} component={props.component}/>) :
    (<Redirect to="/unauthorized/login"/>); 
};

export default PrivateRoute;

【问题讨论】:

  • condition 状态是否更新为真实值? status 的值是多少?
  • useState()的初始数据为什么要设置空字符串?它必须是 falsetrue 用于条件
  • @Danial Falsey values 也可以用于布尔表达式。
  • status 的值为真或假。我已经更新了问题以使其清楚。

标签: reactjs react-hooks


【解决方案1】:

您应该/可以使用第三个“未决”状态,它既不是明确的真也不是假的,并等待 GET 请求解决。没有这个,私有路由组件不会等待解析状态,而是使用错误的 ('') 初始 condition 状态并呈现重定向。

const PrivateRoute = props => {
  const [condition, setCondition] = useState(null);

  useEffect(() => {
    if (!condition) {
      getUserAccess();
    }
  }, [condition]);

  const getUserAccess = async () => {
    try {
      const response = await axios.get("/some-api");
      setCondition(response.data);
    } catch(err) {
      // handle any error logging, etc..
      setCondition(false); // clear "loading state" so redirect can happen
    }
  }

  if (condition === null) {
    return <Spinner />; // or any other "pending" UI indication
  }

  return condition ? (
    <Route {...props} />
  ) : (
    <Redirect to="/unauthorized/login"/>
  );
};

【讨论】:

    【解决方案2】:

    这是因为您的condition 在初始渲染中是!'' = false

    所以它总是达到你的第二个条件:&lt;Redirect to="/unauthorized/login"/&gt; 而没有机会让useEffect 运行。

    要解决这个问题,您需要有一个loading 指示符,让您的组件知道您正在等待响应:

    类似这样的:

    const PrivateRoute = props => {
    const [condition, setCondition] = useState('');
    const [isLoading, setIsLoading] = useState(true);
    
    useEffect(() => {
        if (!condition) {
            getUserAccess();
        }
    }, [condition]);
    
    const getUserAccess = async () => {
        const response = await axios.get("/some-api");
        const status = response.data; /* status will either be true or false */
        setCondition(status);
        setIsLoading(false);
    }
    
    if (isLoading) return <h1>Loading...</h1>;
    
    return condition ? (<Route path={props.path} exact={props.exact} component={props.component}/>) :
        (<Redirect to="/unauthorized/login"/>); 
    };
    
    export default PrivateRoute;
    

    【讨论】:

      【解决方案3】:

      Axios 是基于 Promise 的库

      const [condition, setCondition] = useState(false);
      
      useEffect(() => {
              if (!condition) {
                  axios.get("https://jsonplaceholder.typicode.com/posts/1")
                  .then( (response) =>{
                      //console.log(response.data)
                      setCondition(response.data)
                  })
                  .catch(
                      (error)=>{
                          console.log(error);
                      }
                  )
              }
          }, [condition]);
      

      【讨论】:

      • 条件最初仍为假,重定向将被呈现。您只将 async/await 转换为 Promise 链。你是对的,尽管任何错误或被拒绝的承诺都应该被捕获。
      • Tq 指点我,我认为 catch 块包含您提出的所有内容,但我主要关心的是 setCondition()
      猜你喜欢
      • 2021-03-14
      • 2020-12-07
      • 2019-07-27
      • 2021-04-28
      • 1970-01-01
      • 2022-06-25
      • 2021-10-23
      • 2020-03-08
      • 2020-03-18
      相关资源
      最近更新 更多