React open 从 react-table 弹出
React open pop up from react-table
我正在使用 react.js 构建一个应用程序,它有一个使用 react table library.
构建的 table
在这个 table 中,我想要一个按钮(或其他按钮)来打开一个显示 png 的弹出窗口。 png 由单元格内容决定,因此在所有弹出窗口中可能相同也可能不同。
看来我需要使用一个非常简单的模式,所以我决定使用 react bootstrap library 构建它,如下所示
import React, { useState } from "react";
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
const PopUp = ({ link }) => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Button variant="primary" onClick={handleShow} size="sm">
Pathway
</Button>
<Modal
show={show}
onHide={handleClose}
dialogClassName={'IMG_path'}
size="lg"
>
<Modal.Header closeButton>
<Modal.Title>IMG title</Modal.Title>
</Modal.Header>
<Modal.Body closeButton>
<img src={"./img/" + link}
id="id"
alt="description"
className="img-fluid"/>
</Modal.Body>
</Modal>
</>
);
};
export default PopUp;
然后我在反应 table 旁边测试了它,我的意思是在同一个 div 内,它工作得很好。
然后我使用下面的代码
添加到table
import React from "react";
import { useTable, usePagination, useSortBy } from 'react-table';
import PopUp from "./PopUp";
const MakePopup = ({ values }) => values && <PopUp link={values} /> ;
function Table({ columns, data }) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data,
autoResetPage: true,
initialState: { pageIndex: 0 },
},
// hook for sorting
useSortBy,
// hook for pagination
usePagination
)
return (
<>
<table {...getTableProps()} className={"table table-striped table-bordered table-hover"}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
// Add the sorting props to control sorting. For this example
// we can add them into the header props
<th {...column.getHeaderProps(column.getSortByToggleProps())} scope={"col"}>
{column.render('Header')}
<span>
{column.isSorted
? column.isSortedDesc
? ' '
: ' '
: ''}
</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
{/*
Pagination can be built however you'd like.
This is just a very basic UI implementation:
*/}
<div className="pagination">
<select
value={pageSize}
onChange={e => {
setPageSize(Number(e.target.value))
}}
>
{[10, 20, 30, 40, 50].map(pageSize => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</select>{' '}
<button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
{'<<'}
</button>{' '}
<button onClick={() => previousPage()} disabled={!canPreviousPage}>
{'<'}
</button>{' '}
<span className='page-of'>
Page{' '}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{' '}
</span>
<button onClick={() => nextPage()} disabled={!canNextPage}>
{'>'}
</button>{' '}
<button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
{'>>'}
</button>
</div>
</>
)
}
function MyTable(props) {
const columns = [
{
Header: 'AA',
accessor: 'AA',
},
{
Header: 'BB',
accessor: 'BB',
sortType: "basic"
},
...
...
...
{
Header: 'Img',
accessor: 'url',
sortType: "basic",
disableSortBy: true,
Cell: ({ cell: {value} }) => <MakePopup values={value} />
}
];
const data = props.tableData;
return (
<Table columns={columns} data={data} />
)
}
现在单元格具有调用模式的按钮,但它从未出现:(
在这里搜索我发现 and 答案表明模式应该在 table 之外而不是每个单元格中的下一个按钮所以我将代码修改为这个
import React, { useState } from "react";
import { useTable, usePagination, useSortBy } from 'react-table';
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
// PopUp
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const [link, setLink] = useState('.png');
const handleClick = ( link ) => {
setShow(true);
setLink(link);
};
function Table({ columns, data }) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data,
autoResetPage: true,
initialState: { pageIndex: 0 },
},
// hook for sorting
useSortBy,
// hook for pagination
usePagination
)
return (
<>
<table {...getTableProps()} className={"table table-striped table-bordered table-hover"}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
// Add the sorting props to control sorting. For this example
// we can add them into the header props
<th {...column.getHeaderProps(column.getSortByToggleProps())} scope={"col"}>
{column.render('Header')}
{/* Add a sort direction indicator */}
<span>
{column.isSorted
? column.isSortedDesc
? ' '
: ' '
: ''}
</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
{/*
Pagination can be built however you'd like.
This is just a very basic UI implementation:
*/}
<div className="pagination">
<select
value={pageSize}
onChange={e => {
setPageSize(Number(e.target.value))
}}
>
{[10, 20, 30, 40, 50].map(pageSize => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</select>{' '}
<button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
{'<<'}
</button>{' '}
<button onClick={() => previousPage()} disabled={!canPreviousPage}>
{'<'}
</button>{' '}
<span className='page-of'>
Page{' '}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{' '}
</span>
<button onClick={() => nextPage()} disabled={!canNextPage}>
{'>'}
</button>{' '}
<button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
{'>>'}
</button>
</div>
</>
)
}
function MyTable(props) {
const columns = [
{
Header: 'AA',
accessor: 'AA',
},
{
Header: 'BB',
accessor: 'BB',
sortType: "basic"
},
...
...
...
{
Header: 'Img',
accessor: 'url',
sortType: "basic",
disableSortBy: true,
Cell: ({ cell: { png } }) => png && (
<Button
variant="primary"
onClick={ () => handleClick(png) }
size="sm"
>
Pathway
</Button>
)
}
];
const data = props.genesData;
return (
<>
<Table columns={columns} data={data} />
<Modal
show={show}
onHide={handleClose}
dialogClassName={'IMG_path'}
size="lg"
>
<Modal.Header closeButton>
<Modal.Title>IMG title</Modal.Title>
</Modal.Header>
<Modal.Body closeButton>
<img src={"./img/" + link}
id="id"
alt="description"
className="img-fluid"/>
</Modal.Body>
</Modal>
</>
)
}
export default MyTable;
现在出现以下编译错误,应用程序无法启动
Error: Invalid hook call. Hooks can only be called inside of the body
of a function component. This could happen for one of the following
reasons:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app See react-invalid-hook-call for tips about how to debug and
fix this problem.
指向这部分代码
4 | import Button from 'react-bootstrap/Button';
5 |
6 | // PopUp states
> 7 | const [show, setShow] = useState(false);
8 | const handleClose = () => setShow(false);
9 | // const handleShow = () => setShow(true);
10 | const [link, setLink] = useState('.png');
现在我不确定如何解决这个问题。我一直在考虑使用 redux 之类的状态管理库,但我认为它不能解决问题。我正在使用来自 bootstrap 的模态,但我会使用任何它是什么,因为我认为模态对于我需要的功能来说可能有点太多了。
谢谢
=========================
根据答案编辑
按照@Afzal Zubair 的建议,我将钩子移动到函数内部,如下所示:
import React, { useState } from "react";
import { useTable, usePagination, useSortBy } from 'react-table';
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
function Table({ columns, data }) {
// PopUp states
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
// const handleShow = () => setShow(true);
const [link, setLink] = useState('.png');
const handleClick = ( link ) => {
setShow(true);
setLink(link);
};
const {
getTableProps,
getTableBodyProps,
...
...
...
...
return (
<>
<Table columns={columns} data={data} />
<Modal
show={show}
onHide={handleClose}
dialogClassName={'IMG_path'}
size="lg"
>
<Modal.Header closeButton>
<Modal.Title>KEGG pathway</Modal.Title>
</Modal.Header>
<Modal.Body closeButton>
<img src={"./img/" + link}
alt="plant-pathogen_interaction"
className="img-fluid"/>
</Modal.Body>
</Modal>
</>
)
}
现在我得到一个不同的编译错误
编译失败
./src/components/table/ReactTable_PopUp.jsx Line 193:27:
'handleClick' is not defined no-undef Line 208:15: 'show' is not
defined no-undef Line 209:17: 'handleClose' is not defined
no-undef Line 217:32: 'link' is not defined no-undef
Search for the keywords to learn more about each error.
参考以下代码
190 Cell: ({ cell: { png } }) => png && (
191 <Button
192 variant="primary"
193 onClick={ () => handleClick(png) }
194 size="sm"
195 >
196 Pathway
197 </Button>
198 )
和
204 return (
205 <>
206 <Table columns={columns} data={data} />
207 <Modal
208 show={show}
209 onHide={handleClose}
和
216 <Modal.Body closeButton>
217 <img src={"./img/" + link}
218 alt="plant-pathogen_interaction"
219 className="img-fluid"/>
220 </Modal.Body>
谢谢
============================================= =======================
已解决
@Afzal Zubair 是对的,钩子需要移动到 Functional 元素,我代码中的函数 MyTable
function MyTable(props) {
// PopUp states
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const [link, setLink] = useState('.png');
const handleClick = ( link ) => {
setShow(true);
setLink(link);
};
const columns = [
{
Header: 'AA',
accessor: 'AA',
},
{
Header: 'BB',
accessor: 'BB',
sortType: "basic"
},
...
...
现在可以使用了!
你似乎在 React 组件之外使用了 useState 钩子。
4 | import Button from 'react-bootstrap/Button';
5 |
6 | // PopUp states
> 7 | const [show, setShow] = useState(false);
8 | const handleClose = () => setShow(false);
9 | // const handleShow = () => setShow(true);
10 | const [link, setLink] = useState('.png');
你应该在 Table 组件之外使用模式,但你不能在反应组件之外使用反应钩子。
我建议在 React 组件中使用这些钩子,准确地说是功能组件。
你可以参考这篇文档更好的理解,link.
我正在使用 react.js 构建一个应用程序,它有一个使用 react table library.
构建的 table在这个 table 中,我想要一个按钮(或其他按钮)来打开一个显示 png 的弹出窗口。 png 由单元格内容决定,因此在所有弹出窗口中可能相同也可能不同。
看来我需要使用一个非常简单的模式,所以我决定使用 react bootstrap library 构建它,如下所示
import React, { useState } from "react";
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
const PopUp = ({ link }) => {
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const handleShow = () => setShow(true);
return (
<>
<Button variant="primary" onClick={handleShow} size="sm">
Pathway
</Button>
<Modal
show={show}
onHide={handleClose}
dialogClassName={'IMG_path'}
size="lg"
>
<Modal.Header closeButton>
<Modal.Title>IMG title</Modal.Title>
</Modal.Header>
<Modal.Body closeButton>
<img src={"./img/" + link}
id="id"
alt="description"
className="img-fluid"/>
</Modal.Body>
</Modal>
</>
);
};
export default PopUp;
然后我在反应 table 旁边测试了它,我的意思是在同一个 div 内,它工作得很好。
然后我使用下面的代码
添加到tableimport React from "react";
import { useTable, usePagination, useSortBy } from 'react-table';
import PopUp from "./PopUp";
const MakePopup = ({ values }) => values && <PopUp link={values} /> ;
function Table({ columns, data }) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data,
autoResetPage: true,
initialState: { pageIndex: 0 },
},
// hook for sorting
useSortBy,
// hook for pagination
usePagination
)
return (
<>
<table {...getTableProps()} className={"table table-striped table-bordered table-hover"}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
// Add the sorting props to control sorting. For this example
// we can add them into the header props
<th {...column.getHeaderProps(column.getSortByToggleProps())} scope={"col"}>
{column.render('Header')}
<span>
{column.isSorted
? column.isSortedDesc
? ' '
: ' '
: ''}
</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
{/*
Pagination can be built however you'd like.
This is just a very basic UI implementation:
*/}
<div className="pagination">
<select
value={pageSize}
onChange={e => {
setPageSize(Number(e.target.value))
}}
>
{[10, 20, 30, 40, 50].map(pageSize => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</select>{' '}
<button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
{'<<'}
</button>{' '}
<button onClick={() => previousPage()} disabled={!canPreviousPage}>
{'<'}
</button>{' '}
<span className='page-of'>
Page{' '}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{' '}
</span>
<button onClick={() => nextPage()} disabled={!canNextPage}>
{'>'}
</button>{' '}
<button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
{'>>'}
</button>
</div>
</>
)
}
function MyTable(props) {
const columns = [
{
Header: 'AA',
accessor: 'AA',
},
{
Header: 'BB',
accessor: 'BB',
sortType: "basic"
},
...
...
...
{
Header: 'Img',
accessor: 'url',
sortType: "basic",
disableSortBy: true,
Cell: ({ cell: {value} }) => <MakePopup values={value} />
}
];
const data = props.tableData;
return (
<Table columns={columns} data={data} />
)
}
现在单元格具有调用模式的按钮,但它从未出现:(
在这里搜索我发现
import React, { useState } from "react";
import { useTable, usePagination, useSortBy } from 'react-table';
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
// PopUp
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const [link, setLink] = useState('.png');
const handleClick = ( link ) => {
setShow(true);
setLink(link);
};
function Table({ columns, data }) {
const {
getTableProps,
getTableBodyProps,
headerGroups,
prepareRow,
page,
canPreviousPage,
canNextPage,
pageOptions,
pageCount,
gotoPage,
nextPage,
previousPage,
setPageSize,
state: { pageIndex, pageSize },
} = useTable(
{
columns,
data,
autoResetPage: true,
initialState: { pageIndex: 0 },
},
// hook for sorting
useSortBy,
// hook for pagination
usePagination
)
return (
<>
<table {...getTableProps()} className={"table table-striped table-bordered table-hover"}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
// Add the sorting props to control sorting. For this example
// we can add them into the header props
<th {...column.getHeaderProps(column.getSortByToggleProps())} scope={"col"}>
{column.render('Header')}
{/* Add a sort direction indicator */}
<span>
{column.isSorted
? column.isSortedDesc
? ' '
: ' '
: ''}
</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
{/*
Pagination can be built however you'd like.
This is just a very basic UI implementation:
*/}
<div className="pagination">
<select
value={pageSize}
onChange={e => {
setPageSize(Number(e.target.value))
}}
>
{[10, 20, 30, 40, 50].map(pageSize => (
<option key={pageSize} value={pageSize}>
Show {pageSize}
</option>
))}
</select>{' '}
<button onClick={() => gotoPage(0)} disabled={!canPreviousPage}>
{'<<'}
</button>{' '}
<button onClick={() => previousPage()} disabled={!canPreviousPage}>
{'<'}
</button>{' '}
<span className='page-of'>
Page{' '}
<strong>
{pageIndex + 1} of {pageOptions.length}
</strong>{' '}
</span>
<button onClick={() => nextPage()} disabled={!canNextPage}>
{'>'}
</button>{' '}
<button onClick={() => gotoPage(pageCount - 1)} disabled={!canNextPage}>
{'>>'}
</button>
</div>
</>
)
}
function MyTable(props) {
const columns = [
{
Header: 'AA',
accessor: 'AA',
},
{
Header: 'BB',
accessor: 'BB',
sortType: "basic"
},
...
...
...
{
Header: 'Img',
accessor: 'url',
sortType: "basic",
disableSortBy: true,
Cell: ({ cell: { png } }) => png && (
<Button
variant="primary"
onClick={ () => handleClick(png) }
size="sm"
>
Pathway
</Button>
)
}
];
const data = props.genesData;
return (
<>
<Table columns={columns} data={data} />
<Modal
show={show}
onHide={handleClose}
dialogClassName={'IMG_path'}
size="lg"
>
<Modal.Header closeButton>
<Modal.Title>IMG title</Modal.Title>
</Modal.Header>
<Modal.Body closeButton>
<img src={"./img/" + link}
id="id"
alt="description"
className="img-fluid"/>
</Modal.Body>
</Modal>
</>
)
}
export default MyTable;
现在出现以下编译错误,应用程序无法启动
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
- You might have mismatching versions of React and the renderer (such as React DOM)
- You might be breaking the Rules of Hooks
- You might have more than one copy of React in the same app See react-invalid-hook-call for tips about how to debug and fix this problem.
指向这部分代码
4 | import Button from 'react-bootstrap/Button';
5 |
6 | // PopUp states
> 7 | const [show, setShow] = useState(false);
8 | const handleClose = () => setShow(false);
9 | // const handleShow = () => setShow(true);
10 | const [link, setLink] = useState('.png');
现在我不确定如何解决这个问题。我一直在考虑使用 redux 之类的状态管理库,但我认为它不能解决问题。我正在使用来自 bootstrap 的模态,但我会使用任何它是什么,因为我认为模态对于我需要的功能来说可能有点太多了。
谢谢
=========================
根据答案编辑
按照@Afzal Zubair 的建议,我将钩子移动到函数内部,如下所示:
import React, { useState } from "react";
import { useTable, usePagination, useSortBy } from 'react-table';
import Modal from 'react-bootstrap/Modal';
import Button from 'react-bootstrap/Button';
function Table({ columns, data }) {
// PopUp states
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
// const handleShow = () => setShow(true);
const [link, setLink] = useState('.png');
const handleClick = ( link ) => {
setShow(true);
setLink(link);
};
const {
getTableProps,
getTableBodyProps,
...
...
...
...
return (
<>
<Table columns={columns} data={data} />
<Modal
show={show}
onHide={handleClose}
dialogClassName={'IMG_path'}
size="lg"
>
<Modal.Header closeButton>
<Modal.Title>KEGG pathway</Modal.Title>
</Modal.Header>
<Modal.Body closeButton>
<img src={"./img/" + link}
alt="plant-pathogen_interaction"
className="img-fluid"/>
</Modal.Body>
</Modal>
</>
)
}
现在我得到一个不同的编译错误
编译失败
./src/components/table/ReactTable_PopUp.jsx Line 193:27: 'handleClick' is not defined no-undef Line 208:15: 'show' is not defined no-undef Line 209:17: 'handleClose' is not defined no-undef Line 217:32: 'link' is not defined no-undef
Search for the keywords to learn more about each error.
参考以下代码
190 Cell: ({ cell: { png } }) => png && (
191 <Button
192 variant="primary"
193 onClick={ () => handleClick(png) }
194 size="sm"
195 >
196 Pathway
197 </Button>
198 )
和
204 return (
205 <>
206 <Table columns={columns} data={data} />
207 <Modal
208 show={show}
209 onHide={handleClose}
和
216 <Modal.Body closeButton>
217 <img src={"./img/" + link}
218 alt="plant-pathogen_interaction"
219 className="img-fluid"/>
220 </Modal.Body>
谢谢
============================================= =======================
已解决
@Afzal Zubair 是对的,钩子需要移动到 Functional 元素,我代码中的函数 MyTable
function MyTable(props) {
// PopUp states
const [show, setShow] = useState(false);
const handleClose = () => setShow(false);
const [link, setLink] = useState('.png');
const handleClick = ( link ) => {
setShow(true);
setLink(link);
};
const columns = [
{
Header: 'AA',
accessor: 'AA',
},
{
Header: 'BB',
accessor: 'BB',
sortType: "basic"
},
...
...
现在可以使用了!
你似乎在 React 组件之外使用了 useState 钩子。
4 | import Button from 'react-bootstrap/Button';
5 |
6 | // PopUp states
> 7 | const [show, setShow] = useState(false);
8 | const handleClose = () => setShow(false);
9 | // const handleShow = () => setShow(true);
10 | const [link, setLink] = useState('.png');
你应该在 Table 组件之外使用模式,但你不能在反应组件之外使用反应钩子。
我建议在 React 组件中使用这些钩子,准确地说是功能组件。 你可以参考这篇文档更好的理解,link.