GVKun编程网logo

如何在 React 中为路由实现“render-as-you-fetch”模式(react router render)

14

在本文中,我们将为您详细介绍如何在React中为路由实现“render-as-you-fetch”模式的相关知识,并且为您解答关于reactrouterrender的疑问,此外,我们还会提供一些关于1

在本文中,我们将为您详细介绍如何在 React 中为路由实现“render-as-you-fetch”模式的相关知识,并且为您解答关于react router render的疑问,此外,我们还会提供一些关于15.React路由 react-router4.x 动态路由以及get传值 React中使用url模块、asp.net – OutputCache和RenderAction缓存整个页面、asp.net-mvc-3 – mvc3 OutputCache RemoveOutputCacheItem RenderAction、bs4 FeatureNotFound: Couldn''t find a tree builder with the features you requested: lxml. Do ...的有用信息。

本文目录一览:

如何在 React 中为路由实现“render-as-you-fetch”模式(react router render)

如何在 React 中为路由实现“render-as-you-fetch”模式(react router render)

如何解决如何在 React 中为路由实现“render-as-you-fetch”模式?

新的 Relay hooks API 将重点放在“render-as-you-fetch”的 React 模式上,到目前为止我真的很喜欢这个。 Relay 的 useQueryLoaderusePreloadedQuery 钩子在大多数情况下可以非常直接地实现这一点。

然而,我正在努力寻找一个关于如何在路由方面实现这种模式的好模式。我发现有两种典型情况使这很难实现。

情况 A:

  1. 用户加载主页 (example.com/)
  2. 用户深入应用树的一部分 (example.com/settings/user/security/authentication)
  3. 然后他们点击一个链接,将他们带到他们应用中完全不相关的部分 (example.com/blog/post-1)

情况 B:

  1. 用户使用 URL 栏而不是使用链接 (example.com/blog/post-1) 转到应用的某个部分

对于这些示例,有两种结果,要么用户通过嵌套子组件或直接通过 URL 进入路由 (example.com/blog/post-1)。因此,我们为这条路线获取数据的方式必须同时支持这两种方法。

我假设我们希望尽早触发此路由的获取,因此当用户单击链接时或我们在页面加载时检测到此路由时。

为了实现这一点,我可以想到三个想法:

  1. 改用 fetch-then-render 模式(例如 Relay 的 useLazyLoadQuery 钩子)
  2. 存储一个函数(比如在 Context 中)并让这条路由的所有链接在它们的 onClick 方法中调用这个函数,并且还有一个 useEffect 用于这个路由,如果没有数据已加载,或者查询的引用已过时
  3. 使用 render-as-you-fetch 函数但实现它们以支持 fetch-then-render

方法一:

这违背了 render-as-you-fetch 模式的目的,但它是一种简单的方法,更有可能是实现路由数据获取的“更干净”的方法。

方法 2:

在实践中,我发现这真的很难实现。通常,指向路由的链接与组件呈现路由所在的组件树的部分断开连接。使用上下文意味着我必须为特定路由管理不同的 loadData 函数(当涉及变量等时,这可能会很棘手)。

方法 3:

这就是我目前一直在做的事情。在实践中,它通常会导致能够将加载数据函数传递给附近的组件,但是如果路由被断开连接的组件、URL 或页面重新加载等访问,则组件会回退到调用加载useEffect 钩子中的数据函数。

有没有人有任何其他关于他们如何实现这一点的想法或例子?

解决方法

我也一直在努力理解这一点。我发现这些资源特别有用:

  • Ryan Solid 解释如何实施 fetch-as-you-render
  • ReactConf 2019 Relay demo
  • 中继Issue Tracker example

据我了解,他们希望您实现的目标是:

  • 在渲染路径之前和之外开始加载您的查询
  • 在查询 (code splitting) 的同时开始加载您的组件
  • 将预加载的查询引用传递到组件中

在 Relay 演示中解决这个问题的方法是通过他们称为“入口点”的东西。这些都大量集成到他们的路由器中(您可以在问题跟踪器示例中看到这一点)。它们包括以下组件:

  1. 路由定义(例如 /items
  2. 惰性组件定义(例如 () => import(''./Items'')
  3. 启动查询加载的函数(例如 () => preloadQuery(...)

当路由器匹配一个新路径时,它开始加载惰性组件的过程,以及查询。然后它将这两个传递给一个上下文对象以由它们的 RouterRenderer 呈现。

至于如何实现这一点,似乎最重要的规则是:

  1. 不要在组件内部请求数据,而是在路由或事件级别请求数据
  2. 确保同时请求数据和惰性组件

一个简单的解决方案似乎是创建一个负责收集数据的组件,然后渲染相应的组件。类似的东西:

const LazyItemDetails = React.lazy(() => import(''./ItemDetails''))

export function ItemEntrypoint() {
   const match = useMatch()
   const relayEnvironment = useEnvironment()
   const queryRef = loadQuery<ItemDetailsQuery>(relayEnvironment,ItemDetailsQuery,{ itemId: match.itemId })
   
   return <LazyItemDetails queryRef={queryRef} />
}

但是,问题跟踪器示例添加了解决方案以解决潜在问题:

  • 惰性组件之前可能已被请求,因此应缓存
  • 数据获取位于渲染路径

相反,问题跟踪器解决方案使用执行组件缓存的路由器,并在匹配路由的同时获取数据(通过侦听历史更改事件)。如果您愿意维护自己的路由器,则可以在自己的代码中使用此路由器。

就现成的解决方案而言,似乎没有一个路由器可以实现执行 fetch-as-you-render 所需的模式。

TL;DR 使用中继 Issue Tracker 示例路由器。

奖励:我已经written a blog post了解了我理解这种模式的过程

15.React路由 react-router4.x 动态路由以及get传值 React中使用url模块

15.React路由 react-router4.x 动态路由以及get传值 React中使用url模块

一.动态路由

定义

<Route path="/content/:aid" component={Content} />    

传值

<Link to={`/content/${value.aid}`}>{value.title}</Link>

获取

    constructor(props) {
        super(props);
        this.state = {  };
    }
    //生命周期函数
    componentDidMount(){
        //获取动态路由的传值
        console.log(this.props.match.params.aid);  
    }

二.get传值

传值

<li key={key}>                                   
    <Link to={`/productcontent?aid=${value.aid}`}>{value.title}</Link>
</li>

获取(引入url模块)

    //生命周期函数
    componentDidMount(){
        // this.props.location.search
        //获取get传值
        console.log(url.parse(this.props.location.search,true));
        var query=url.parse(this.props.location.search,true).query;
        console.log(query)
    }

 

首页组件


/*

  react路由的配置:
    1、找到官方文档 https://reacttraining.com/react-router/web/example/basic

    2、安装  cnpm install react-router-dom --save


    3、找到项目的根组件引入react-router-dom

       import { BrowserRouter as Router, Route, Link } from "react-router-dom";

    4、复制官网文档根组件里面的内容进行修改  (加载的组件要提前引入)


         <Router>

                <Link to="/">首页</Link>

                <Link to="/news">新闻</Link>

                <Link to="/product">商品</Link>


               <Route exact path="/" component={Home} />
               <Route path="/news" component={News} />    
               <Route path="/product" component={Product} />   
         </Router>


         exact表示严格匹配


react动态路由传值

      1、动态路由配置

          <Route path="/content/:aid" component={Content} />   

      2、对应的动态路由加载的组件里面获取传值

            this.props.match.params


      跳转:<Link to={`/content/${value.aid}`}>{value.title}</Link>

react get传值  


      1、获取 this.props.location.search


      

         
*/



import React, { Component } from ''react'';

import { BrowserRouter as Router, Route, Link } from "react-router-dom";


import ''./assets/css/index.css''

import Home from ''./components/Home'';
import News from ''./components/News'';
import Product from ''./components/Product'';
import Content from ''./components/Content'';

import ProductContent from ''./components/ProductContent'';

class App extends Component {

  render() {
    return (
        <Router>
          <div>           

              <header className="title">
              
                <Link to="/">首页</Link>

                <Link to="/news">新闻</Link>

                <Link to="/product">商品</Link>

              </header>


               <br />
               <hr />
      
               <br />
      
      
              <Route exact path="/" component={Home} />
              <Route path="/news" component={News} />    
              <Route path="/product" component={Product} /> 
              <Route path="/productcontent" component={ProductContent} />

              <Route path="/content/:aid" component={Content} />                 
          </div>
      </Router>
    );
  }
}

export default App;

 

动态路由

新闻组件

import React, { Component } from ''react'';
import { Link } from "react-router-dom";

class News extends Component {
    constructor(props) {
        super(props);
        this.state = {  

            list:[

                {
                    aid:''11'',
                    title:''我是新闻1111''
                },
                {
                    aid:''222'',
                    title:''我是新闻222''
                },
                {
                    aid:''3'',
                    title:''我是新闻333''
                },
                {
                    aid:''4'',
                    title:''我是新闻4444''
                }
            ]
        };
    }
    render() {
        return (
            
            <div>

                我是新闻组件

                <ul>
                    {

                        this.state.list.map((value,key)=>{

                            return (
                                <li key={key}>                                   
                                    <Link to={`/content/${value.aid}`}>{value.title}</Link>
                                </li>
                            )
                        })
                    }
                    
                </ul>
            </div>
        );
    }
}

export default News;

 

新闻详情组件

import React, { Component } from ''react'';


class Content extends Component {
    constructor(props) {
        super(props);
        this.state = {  };
    }
    //生命周期函数
    componentDidMount(){


        //获取动态路由的传值
        console.log(this.props.match.params.aid);  

    }
    render() {
        return (
            
            <div>

                我是新闻详情组件
            </div>
        );
    }
}

export default Content;

 

 

get传值

import React, { Component } from ''react'';

import { Link } from "react-router-dom";
class Product extends Component {
    constructor(props) {
        super(props);
        this.state = { 

            list:[

                {
                    aid:''11'',
                    title:''我是商品1111''
                },
                {
                    aid:''222'',
                    title:''我是商品222''
                },
                {
                    aid:''3'',
                    title:''我是商品333''
                },
                {
                    aid:''4'',
                    title:''我是商品4444''
                }
            ]
         };
    }
    render() {
        return (
            
            <div>

                我是商品组件

                 <ul>
                    {

                        this.state.list.map((value,key)=>{

                            return (
                                <li key={key}>                                   
                                    <Link to={`/productcontent?aid=${value.aid}`}>{value.title}</Link>
                                </li>
                            )
                        })
                    }
                    
                </ul>
            </div>
        );
    }
}

export default Product;

 

详情组件

import React, { Component } from ''react'';

//url模块来解析url地址    在react里面使用url模块需要安装url模块    cnpm install url --save
import url from ''url'';


class ProductContent extends Component {
    constructor(props) {
        super(props);
        this.state = {  };
    }
    //生命周期函数
    componentDidMount(){



        // this.props.location.search


        //获取get传值

        console.log(url.parse(this.props.location.search,true));

        var query=url.parse(this.props.location.search,true).query;

        console.log(query)

        

    }
    render() {
        return (
            
            <div>

                我是商品详情组件
            </div>
        );
    }
}

export default ProductContent;

 

 

asp.net – OutputCache和RenderAction缓存整个页面

asp.net – OutputCache和RenderAction缓存整个页面

我有一个ViewPage包含<% Html.RenderAction< MyController>(c => c.SidebarStats()); %取代.在操作SidebarStats的控制器操作上,我有一个OutputCache操作过滤器,只缓存页面的那一部分.但是,整个页面正在缓存,而不仅仅是该操作.

我记得在某个地方看到这可能是ASP.NET MVC的一个错误,虽然我不确定.我目前正在使用ASP.NET MVC RC1,IIS7,Windows Server 2008和.NET 3.5 SP1.

解决方法

我写了一个 solution to this problem here.这很简单,但只有在你使用WebFormViewEngine时它才有效.我们将仔细研究如何使所有视图引擎都能正常工作.

asp.net-mvc-3 – mvc3 OutputCache RemoveOutputCacheItem RenderAction

asp.net-mvc-3 – mvc3 OutputCache RemoveOutputCacheItem RenderAction

我做了我的研究,但没有找到任何答案.

我在主页面中使用Html.RenderAction(用于呈现具有特定于用户权限的链接的页眉). Action使用OutputCache修饰,返回部分控制并按预期缓存.

当事件发生时(假设权限已更改)我想以编程方式使缓存的部分控件无效.

我正在尝试使用RemoveOutputCacheItem方法.它将路径作为参数.我正在尝试设置Html.RenderAction中使用的操作的路径.这不会使行动失效.

如何以编程方式使操作无效?

谢谢

解决方法

子操作的缓存存储在 OutputCacheAttribute.ChildActionCache属性中.问题是,为子操作生成id并将其存储在此对象中的API不公开(为什么是微软?).因此,如果您尝试遍历此集合中的对象,您将发现它还将包含子操作的缓存值,但除非您反向设计用于生成键的算法,否则您将无法识别它像这样的东西(如Reflector所示):
internal string GetChildActionUniqueId(ActionExecutingContext filterContext)
{
    StringBuilder builder = new StringBuilder();
    builder.Append("_MvcChildActionCache_");
    builder.Append(filterContext.ActionDescriptor.UniqueId);
    builder.Append(DescriptorUtil.CreateUniqueId(new object[] { this.varyByCustom }));
    if (!string.IsNullOrEmpty(this.varyByCustom))
    {
        string varyByCustomString = filterContext.HttpContext.ApplicationInstance.GetvaryByCustomString(HttpContext.Current,this.varyByCustom);
        builder.Append(varyByCustomString);
    }
    builder.Append(GetUniqueIdFromActionParameters(filterContext,SplitvaryByParam(this.varyByParam)));
    using (SHA256 sha = SHA256.Create())
    {
        return Convert.ToBase64String(sha.ComputeHash(Encoding.UTF8.GetBytes(builder.ToString())));
    }
}

所以你可以执行以下疯狂:

public ActionResult Invalidate()
{
    OutputCacheAttribute.ChildActionCache = new MemoryCache("NewDefault");
    return View();
}

这显然会使所有缓存的子操作无效,这些操作可能不是您正在寻找的但我担心除了当然是对密钥生成进行逆向工程之外的唯一方法:-).

@Microsoft,拜托,我求你了解ASP.NET MVC 4.0:

>除了甜甜圈洞缓存之外,还介绍了进行甜甜圈缓存的可能性>介绍了轻松过期缓存控制器操作结果的可能性(比Response.RemoveOutputCacheItem更多MVCish)>介绍轻松过期缓存子操作的结果的可能性>如果你这样做1.那么显然有可能使缓存的甜甜圈部分到期.

bs4 FeatureNotFound: Couldn''t find a tree builder with the features you requested: lxml. Do ...

bs4 FeatureNotFound: Couldn''t find a tree builder with the features you requested: lxml. Do ...

安装 beautifulsoup 后,运行测试报错

from urllib import request
from bs4 import BeautifulSoup

url = "http://www.baidu.com"
rsp = request.urlopen(url)
content = rsp.read()

soup = BeautifulSoup(content, "lxml")

print(soup.title.string)
----------------------------------------------------------------------
FeatureNotFound                      Traceback (most recent call last)
~/data/spider/bs.py in <module>
     16 content = rsp.read()
     17
---> 18 soup = BeautifulSoup(content, "lxml")
     19
     20 print(soup.title.string)

~/data/spider/venv/lib/python3.7/site-packages/bs4/__init__.py in __init__(self, markup, features, builder, parse_only, from_encoding, exclude_encodings, **kwargs)
    196                     "Couldn''t find a tree builder with the features you "
    197                     "requested: %s. Do you need to install a parser library?"
--> 198                     % ",".join(features))
    199             builder = builder_class()
    200             if not (original_features == builder.NAME or

FeatureNotFound: Couldn''t find a tree builder with the features you requested: lxml. Do you need to install a parser library?

经过测试发现是 lxml 的问题,使用 pip install lxml 安装,安装完后,在运行还是一样出错,经百度、知乎的说法是新的库不支持,新版本语法支持改变了

使用 pip install lxml 时,自动安装的是最新 4.2.5 版本

解决方法一:

  卸载新的换老的就可以了

    pip uninstall lxml

    pip install lxml==3.7.0

方法二:

 在报错代码中把函数参数中所有的"lxml"改成"html.parser"
soup = BeautifulSoup(content, "lxml")
改成 soup = BeautifulSoup(content, "html.parser")

今天关于如何在 React 中为路由实现“render-as-you-fetch”模式react router render的介绍到此结束,谢谢您的阅读,有关15.React路由 react-router4.x 动态路由以及get传值 React中使用url模块、asp.net – OutputCache和RenderAction缓存整个页面、asp.net-mvc-3 – mvc3 OutputCache RemoveOutputCacheItem RenderAction、bs4 FeatureNotFound: Couldn''t find a tree builder with the features you requested: lxml. Do ...等更多相关知识的信息可以在本站进行查询。

本文标签: