从 react-bootstrap-table2 的列渲染器中使用 Location hook 获取位置路径

Posted

技术标签:

【中文标题】从 react-bootstrap-table2 的列渲染器中使用 Location hook 获取位置路径【英文标题】:Get location path from use Location hook inside a column renderer from react-bootstrap-table2 【发布时间】:2021-08-30 22:50:05 【问题描述】:

故事

我正在使用 react.js 创建 2 个页面(摘要和循环页面)。

在“摘要”页面上,有一个名为 CN 的列,每个项目都链接到“周期”页面。

摘要页面有一个路径/route/summary/location=abc,循环页面有一个路径/route/cycle/location=abc/deviceId=4410

例如,如果我单击摘要页面内表格第一行中CN 列中的值,我将被重定向到路径为/route/cycle/location=abc/deviceId=4410 的循环页面。

在摘要页面中,我使用https://github.com/react-bootstrap-table/react-bootstrap-table2 作为表格组件,并在columns.js 中使用columnRenderer 函数在表格中呈现一个自定义项,如下所示:

问题

如何将pathname(例如“abc”)放入columns.jscnColumnRenderer 函数内的链接组件?

我想要的理想状态:

带有路径的摘要页面:/route/summary/location=abc

循环页面的路径:/route/cycle/location=abc/deviceId=4410

实际情况:

渲染摘要页面时由于无效的钩子调用而出错

我的代码:

摘要页面内的表格代码(Summary.js内):

提示:关注 './columns' 中的 columns 变量及其实现

import React from "react"
import  useLocation  from "react-router-dom"

import BootstrapTable from 'react-bootstrap-table-next';
import paginationFactory, 
    PaginationProvider,
    PaginationListStandalone
 from 'react-bootstrap-table2-paginator';
import ToolkitProvider,  Search  from 'react-bootstrap-table2-toolkit';

import columns from './columns'

const Summary = () =>     
    const location = useLocation()
    const locationName = location['pathname'].replace('/route/summary/location=', '')
    // console.log('Summary, location:', locationName)
    // example: location = "/route/summary/location=abc" and locationName = "abc"

    // ...some code here...

    return (
        <React.Fragment>
            <div className="container-fluid ppa-route-summary-root">
                <Row>
                    <Col className="col-12">

                        /* ...some code here... */

                        /* TABLE CARD */
                        <Card>
                            <CardBody>
                                <PaginationProvider
                                    pagination=paginationFactory(paginationOptions)
                                    keyField='id'
                                    columns=columns
                                    data=tableData
                                >
                                    
                                        ( paginationProps, paginationTableProps ) => (
                                            <ToolkitProvider
                                                keyField='id'
                                                columns=columns
                                                data=tableData
                                                search
                                            >
                                                
                                                    toolkitProps => (
                                                        <React.Fragment>

                                                            /* ...some code here... */

                                                            /* TABLE ITSELF */
                                                            <Row>
                                                            <Col xl="12">
                                                                <div className="table-responsive">
                                                                    
                                                                        isTableLoading ? 
                                                                        <ReactLoading 
                                                                            type='spin' 
                                                                            color='crimson' 
                                                                            height='5rem' 
                                                                            width='5rem' 
                                                                            className='table-loading'
                                                                        /> :
                                                                        <BootstrapTable
                                                                            keyField="id"
                                                                            responsive
                                                                            bordered=false
                                                                            striped=false
                                                                            // defaultSorted=defaultSorted
                                                                            // selectRow=selectRow
                                                                            classes=
                                                                                "table align-middle table-nowrap"
                                                                            
                                                                            headerWrapperClasses="thead-light"
                                                                            ...toolkitProps.baseProps
                                                                            ...paginationTableProps
                                                                        />
                                                                    
                                                                </div>
                                                            </Col>
                                                            </Row>

                                                            /* ...some code here... */

                                                        </React.Fragment>
                                                    )
                                                
                                            </ToolkitProvider>
                                        )
                                    
                                </PaginationProvider>
                            </CardBody>
                        </Card>
                    </Col>
                </Row>
            </div>
        </React.Fragment>
    )


export default Summary

columns.js

import React from 'react'
import  Link, useLocation  from 'react-router-dom'

// IMAGES
import IconLocation from '../../../images/icons/location.svg'

const cnColumnRenderer = (cell, row, rowIndex, formatExtraData) => 
    // console.log('columns, cnColumnRenderer:', cell, row, rowIndex, formatExtraData)
    const deviceVersion = cell.split('-')[1] // example: deviceVersion = "4410"

    const location = useLocation()
    // console.log('Summary columns, location:', location['pathname'])

    // here is the pathname I wanted: "/route/cycle/location=abc" so I can take the "location" path value as below:
    const locationName = location['pathname'].replace('/route/summary/location=', '') // the result is locationName = "abc"
    // then put the locationName inside the Link component

    return(
        <div className='route-summary-cn'>
            <img src=IconLocation alt='' className='icon-location'/>
            /* below is the pathname I wanted: "/route/cycle/location=abc/deviceId=4410" */
            <Link to=`/route/summary/location=$locationName/deviceId=$row['deviceId']`>
                deviceVersion
            </Link>
        </div>
    )


const columns = [
    
        dataField: 'deviceName',
        text: 'CN',
        formatter: cnColumnRenderer,
        sort: true
    ,
    
        dataField: 'convertedTotalCycle',
        text: 'Cycle',
        sort: true,
    ,
    // ...some code here...
]

export default columns

注意:如果问题令人困惑,请告诉我。我会尝试更新它。

【问题讨论】:

React 钩子仅在 React 功能组件中有效,在任何回调、循环、条件块中无效。如果您需要回调中的位置数据,则需要将其传入。 你能告诉我我应该使用@DrewReese 的代码吗? 【参考方案1】:

React 钩子仅在 React 函数式组件中有效,在任何回调、循环、条件块中无效。如果需要回调中的位置数据,则需要传入。

据我所知,您似乎需要将columns.js 代码移入 主要组件,以便可以在范围内关闭location 值。

const Summary = () =>     
  const location = useLocation();

  const locationName = location['pathname'].replace('/route/summary/location=', '')
  // example: location = "/route/summary/location=abc" and locationName = "abc"

  // ...some code here...

  const cnColumnRenderer = (cell, row, rowIndex, formatExtraData) => 
    // console.log('columns, cnColumnRenderer:', cell, row, rowIndex, formatExtraData)
    const deviceVersion = cell.split('-')[1] // example: deviceVersion = "4410"

    // then put the locationName inside the Link component

    return(
      <div className='route-summary-cn'>
        <img src=IconLocation alt='' className='icon-location'/>
        /* below is the pathname I wanted: "/route/cycle/location=abc/deviceId=4410" */
        <Link to=`/route/summary/location=$locationName/deviceId=$row['deviceId']`>
          deviceVersion
        </Link>
      </div>
    );
  ;

  const columns = [
    
      dataField: 'deviceName',
      text: 'CN',
      formatter: cnColumnRenderer,
      sort: true
    ,
    
      dataField: 'convertedTotalCycle',
      text: 'Cycle',
      sort: true,
    ,
    // ...some code here...
  ];

  return (
    ...
  );

【讨论】:

感谢您的回答。我也是这么想的,但是如果我实现这个代码,Summary.js 的代码会很长。这就是为什么我尝试将一些小组件移到 Summary.js 之外的原因。我想知道是否有任何正确的方法可以在 Summary.js 之外声明 cnColumnRenderer 和列?如果不是,我会改用这个想法。 @JabalLogian 您可以将cnColumnRenderer 转换为工厂函数,该函数接受location 对象并返回格式化函数。 columns 仍然需要在 Summary 中声明,以便它可以使用 location。如果您有兴趣,我可以将其添加到我的答案中。 感谢您的评论。如果columns仍然需要在Summary.js中声明,我想我会选择第一个解决方案。非常感谢,德鲁里斯。

以上是关于从 react-bootstrap-table2 的列渲染器中使用 Location hook 获取位置路径的主要内容,如果未能解决你的问题,请参考以下文章

react-bootstrap-table 未对齐的标题列

当我使用 ReactJS 从数据表中删除行而不使用 Redux 或 Context 时,如何刷新数据表?

UNMET PEER DEPENDENCY react-router@3.0.0

Grails 从 2.2.1 升级到 2.3.4 @Secured Annotation

将 MongoDB 从 2.6 升级到 4.2.6

将颤振从 2.5 升级到 2.8 后出错