ãããããŒãã«ã§äœ¿çšããäŸã¯ãããŸããïŒ ç§ã¯ãããæ©èœãããããšããŠããŸããããããæ©èœããªãããäœãéåžžã«ééã£ãããšãããŠããã®ã§ã¯ãªãããšåŒ·ãçã£ãŠããŸãã
outerTagNameã "table"ã«ãinnerTagNameã "tbody"ã«èšå®ããŸããããã¹ã¯ããŒã«ã§ããŸããã
ãããç§ã®ã³ãŒãã§ãããããã圹ç«ã€ãã©ããã¯ããããŸããïŒã¢ã€ãã ã¯ãªããžã§ã¯ãã®ãªã¹ãã§ãïŒïŒ
<List
outerRef={this._list}
outerTagName="table"
innerTagName="tbody"
height={300}
itemData={items}
itemSize={() => 30}
itemCount={items.length}
itemKey={item => item.uniqueId}>
{({index, style, data}) => {
return (
<tr style={style} key={index}>
<td>Item {index}</td>
</tr>
);
}}
</List>
ãããå®éã«æ©èœãããšã¯æããªãã ç§ã®ç¥ãéãã HTMLTableElement
ã¯ããŠã£ã³ããŠã³ã³ããŒãã³ããå¿
èŠãšãããããªãªãŒããŒãããŒãå®éã«ã¯ãµããŒãããŠããŸããã ã¹ã¿ã€ã«ãdisplay: block
å€æŽããããšã¯ã§ããŸãããããã§ãæ£ããæ©èœãããšã¯æããŸããã ïŒãããäŸã§ããïŒ
ãªãããŒãã«ãå¿ èŠãªã®ã§ããïŒ ã€ã³ã©ã€ã³ãããã¯ãŸãã¯ãã¬ãã¯ã¹ã¬ã€ã¢ãŠãã§åãåã¬ã€ã¢ãŠããå®çŸã§ãããšæããŸãã
è¿œå äºé ã®ã«ããã«ïŒ
width
ããList
æå®ããŠããŸããkey
ãè¿œå ããå¿
èŠã¯ãããŸããitemSize
ã¯ã () => 30
ã§ã¯ãªã30
ã«ããããšãã§ããŸãïŒããã©ãŒãã³ã¹ã¯ãããã«åäžããŸãïŒæ©éã®ãè¿äºããããšãããããŸãã
divãžã®æžãæãã«ã€ããŠã¯ãã§ã«èª¬æããŸããããããã¯æ¢åã®ããªã倧ããªã³ã³ããŒãã³ãçšã§ãããããæžãæããéå§ããåã«ç¢ºèªãããã£ãã ãã§ãã rc-tableã«ã€ããŠä»ã«ãã³ã¡ã³ãããã£ãã®ã§ãããŸãããã¯ãã ãšæããŸããã
ãšã«ãããæžãçŽããæ°ã«ããªãã§ãã ãããããã¯ç§ãæã䟡å€ãããã¯ãã§ãã
è¡ã«ããŒããªãããŒã«ã€ããŠReactã®èŠåã衚瀺ãããŸãããããã¯ãitemKeyãèšå®ããŠããããšãèãããšæ··ä¹±ãæããããã§äœãèµ·ãã£ãŠããã®ãããããŸããã
ããããšã
ãšã€ãã«
2018幎9æ21æ¥ã«ã¯ãåå16æ52åã§ããã©ã€ã¢ã³ã»ãŽã©ãŒã³ã®[email protected]ã¯æžããŸããïŒ
ãããå®éã«æ©èœãããšã¯æããªãã ç§ã®ç¥ãéããHTMLTableElementã¯ããŠã£ã³ããŠã³ã³ããŒãã³ããå¿ èŠãšãããããªãªãŒããŒãããŒãå®éã«ã¯ãµããŒãããŠããŸããã 衚瀺ããã¹ã¿ã€ã«ãå€æŽããããšãã§ããŸãïŒãããã¯ã§ãããããã§ãæ£ããæ©èœãããšã¯æããŸããã
ãªãããŒãã«ãå¿ èŠãªã®ã§ããïŒ ã€ã³ã©ã€ã³ãããã¯ãŸãã¯ãã¬ãã¯ã¹ã¬ã€ã¢ãŠãã§åãåã¬ã€ã¢ãŠããå®çŸã§ãããšæããŸãã
è¿œå äºé ã®ã«ããã«ïŒ
ãªã¹ãã«å¿ é ãã©ã¡ãŒã¿ãŒå¹ ãæå®ããŠããŸãã
è¡ã«ããŒãè¿œå ããå¿ èŠã¯ãããŸãã
itemSizeã¯ãïŒïŒ=> 30ã§ã¯ãªã30ã«ããããšãã§ããŸãïŒããã©ãŒãã³ã¹ããããã«åäžããŸãïŒ
â
ã¹ã¬ãããäœæããããããããåãåã£ãŠããŸãã
ãã®ã¡ãŒã«ã«çŽæ¥è¿ä¿¡ããããGitHubã§è¡šç€ºããããã¹ã¬ããããã¥ãŒãããŠãã ããã
è¡ã«ããŒããªãããŒã«ã€ããŠReactã®èŠåã衚瀺ãããŸãããããã¯ãitemKeyãèšå®ããŠããããšãèãããšæ··ä¹±ãæããããã§äœãèµ·ãã£ãŠããã®ãããããŸããã
ããã¯äºæãããŠããŸããã ïŒã³ãŒããµã³ãããã¯ã¹ãä»ããŠïŒåçŸã±ãŒã¹ãç§ãšå ±æã§ããŸããïŒ
ãããããããªããã itemKey
é¢æ°ãäžéšã®ã¢ã€ãã ã«å¯ŸããŠundefined
ãè¿ããå Žåã«ã®ã¿ããããäºæ³ãããããšãè¿œå ããå¿
èŠããããŸãããã®å Žåããã®é¢æ°ãä¿®æ£ããå¿
èŠããããŸãã
@bvaughnãªãŒããŒãããŒãµããŒããå¶éèŠå ã§ããããšã«å ·äœçãªããšã¯äœãèŠã€ãããŸããã äžæè°ãªããšã«ããããäœã§ãããç¥ãããã®ã§ããã 確ãã«ãäž¡æ¹ã®ã³ã¢æ©èœããµããŒãããã®ã¯é¢åãããããŸããããçŸæç¹ã§ã¯ãåºæ¬ãªã¹ãèŠçŽ ã ããå®è£ è ã®éžæããå€ããŠããããã«èŠããŸãã ç§èªèº«ãšãåºå®ããããŒã·ããªãªã§react-windowã䜿çšããŠããå¯èœæ§ã®ãã人ãªã誰ã§ããããŒãã«ã¬ã€ã¢ãŠãã«çµã¿èŸŒãŸããåºæã®è¡šåœ¢åŒã®ãµããŒããååŸãããšããã§ãããã displayã®äœ¿çšïŒtableã¯ãããããã®ãéçºãªãŒããŒããããå¿ èŠãšããå¶ç¶ã«ããŒãã«ã䜿çšããŠæ§ç¯ãããå¯èœæ§ã®ããåšå²ã®ã¢ããªã±ãŒã·ã§ã³åãã®1åéãã®ã¬ã€ã¢ãŠãã§ãã ç§ã¯ãã€ã§ãcssãä»ããŠãªãŒããŒãããŒãä»ã®ããããã£ã埮調æŽããããšãã§ããŸããïŒãšã«ããçŸåšã®å®è£ ã§ãããè¡ã£ãŠããŸãïŒã elementTypeããããã¯åé¡å€ã§ããïŒ
@bvaughnãªãŒããŒãããŒãµããŒããå¶éèŠå ã§ããããšã«å ·äœçãªããšã¯äœãèŠã€ãããŸããã
ããããç§ã¯æé«ã®èšãåãã䜿çšããŠããŸããã§ãããããªã³ã¯ãããµã³ãããã¯ã¹ïŒ rrn61wkzwm ïŒãèŠããšãäºæããªãåäœãèŠãããŸãã
ããã¯HTMLã ãã®å¥ã®äŸã§ãïŒ lx65871p69
HTMLSelectElement
ïŒ <tbody>
ïŒã¯ã height
ãoverflow
ãªã©ã®ã¹ã¿ã€ã«ãç¡èŠããããããŠã£ã³ããŠåŠçã«ã¯äœ¿çšã§ããŸããã 衚瀺ã¢ãŒãïŒ display: block
ïŒãå€æŽããããšã§ããããä¿®æ£ãã§ããŸãããåã®ãµã€ãºå€æŽåäœãæãªãããããã HTMLTableElement
ã䜿çšããç®çãç¡å¹ã«ãªããŸãã
ãµã€ãºã¯åã®ã³ã³ãã³ãã«äŸåããããïŒãŠãŒã¶ãŒãã¹ã¯ããŒã«ãããšå€åããããïŒããŠã£ã³ããŠã®ãŠãŒã¹ã±ãŒã¹ã§ã¯ããããããã®åã®ãµã€ãºèšå®ã®åäœã¯å£ããŠããŸãã
ããããçŸæç¹ã§ã¯ãåºæ¬ãªã¹ãèŠçŽ ã ããå®è£ è ã®éžæããå€ããŠããããã«èŠããŸã... elementTypeããããã¯åé¡å€ã§ããïŒ
æ¬åœã«å¿ èŠãªå Žåã¯ïŒ 2j0z718mwy ïŒãã¿ã°ã¿ã€ãããã§ã«æå®ã§ããŸãããäœãåŸããããã¯ããããŸããã
ç§èªèº«ãšãåºå®ããããŒã·ããªãªã§react-windowã䜿çšããŠããå¯èœæ§ã®ãã人ãªã誰ã§ããããŒãã«ã¬ã€ã¢ãŠãã«çµã¿èŸŒãŸããåºæã®è¡šåœ¢åŒã®ãµããŒããååŸãããšããã§ãããã
HTMLTableElement
ã䜿çšãããšãäžèšã§èª¬æããçç±ã§åé¡ãçºçããŸãã ããããŒãåºå®ããã衚圢åŒ/ã°ãªããã¬ã€ã¢ãŠããå¿
èŠãªå Žåã¯ãéåžžã®ãªã¹ãã³ã³ããŒãã³ãã®1ã€ã䜿çšããŠãããå®çŸã§ããŸãïŒ pk78pvwnkx
ãªãããŒãã«ãå¿ èŠãªã®ã§ããïŒ ã€ã³ã©ã€ã³ãããã¯ãŸãã¯ãã¬ãã¯ã¹ã¬ã€ã¢ãŠãã§åãåã¬ã€ã¢ãŠããå®çŸã§ãããšæããŸãã
ã¢ã¯ã»ã·ããªãã£ã®ããã«ããŒãã«æ§é ãå¿ èŠãªã®ãããããŸããïŒããšãã°ãéã»ãã³ãã£ãã¯divãšæ¯èŒããŠããè¯ãç»é¢èªã¿äžãïŒïŒ ç§ã¯ããã§æšæž¬ããŠããŸãã
ãã®å ŽåãCSSã®è¡šç€ºã¹ã¿ã€ã«ãããŒãã«èŠçŽ ã«åºæã®ä»ã®ã¹ã¿ã€ã«ããªãŒããŒã©ã€ãããŸãã
çŽ9幎åã«è€éãªããŒãã«ã³ã³ããŒãã³ãïŒäžäžã«åºå®/åºå®ãããèŠåºããè€éãªcolspan / rowspanæ§é ãããã³ãã®èåŸã«ããæ§é ã説æããããŒã¿ã¢ãã«ãå«ãïŒãæ§ç¯ããç§ã®çµéšïŒåœæã¯Reactããã¢ã¯ã»ã·ããªãã£ã®æžå¿µããããŸããã§ããä»®æ³åããªãããšãèŠããŠããéãïŒãã®ã³ã³ããŒãã³ããæ åœããååã¯ãé©åãªããŒãã«èŠçŽ ã«ã³ã³ããŒãã³ããå®è£ ããããšããã¬ã€ã¢ãŠããç¹å®ã®æ¹æ³ã§åäœãããã®ã«èŠåŽããããçŽç²ãªJavaScriptã§ããŒãã«ã¬ã€ã¢ãŠããå®è£ ããããšã«ããŸããã絶察ã«é 眮ããããµã€ãºèšå®ãããdivã ãã®ãœãªã¥ãŒã·ã§ã³ã¯å®å šã«æ©èœããŸãããå¥åŠãªã¬ã€ã¢ãŠããžã£ã³ããã¹ã ãŒãºãªã¹ã¯ããŒã«ïŒè¡ããš/åããšã§ã¯ãªãïŒãªã©ã¯ãããŸããã
ã¢ã¯ã»ã·ããªãã£ã®ããã«ããŒãã«æ§é ãå¿ èŠãªã®ãããããŸããïŒããšãã°ãéã»ãã³ãã£ãã¯divãšæ¯èŒããŠããè¯ãç»é¢èªã¿äžãïŒïŒ ç§ã¯ããã§æšæž¬ããŠããŸãã
ããã«ã¯Ariaã®åœ¹å²ã䜿çšã§ããŸãð
è¶ åŸ¹åºãããããšãããããŸãã ããåé¡ã解決ããŠä»ã®åé¡ãäœæããã ãã®ãããã¿ã€ããè©Šãããã«ããããã®ç©Žãäžã£ãŠè¡ãã®ãå©ããŠãããŸããã
ããã«ã¡ã¯
æ°ããã¹ã¬ãããäœæãã代ããã«ãæ¢åã®ã¹ã¬ãããèŠã€ããããšããŸããã ç§ã¯è¯ãå Žæã«ããããšãé¡ã£ãŠããŸã...
FixedSizeGrid
2ã€ã®ã»ã«ãããŒãžããäžçš®ã®ãcolspanããæã€æ¹æ³ã¯ãããŸããïŒç§ã®ã³ã³ããã¹ãã§ã¯ãããããã£ãšæå³ããããŸãïŒïŒ
ãã®è³ªåã¯ãããã§å§ãŸã£ãå¥ã®è°è«ã«äŸåããŠã
FixedSizeGridã®2ã€ã®ã»ã«ãããŒãžããããã®äžçš®ã®ãcolspanããæã€æ¹æ³ã¯ãããŸããïŒç§ã®ã³ã³ããã¹ãã§ã¯ãããããã£ãšæå³ããããŸãïŒïŒ
ããããããã¯ãµããŒããããŠããŸããã
@einarq @BlaineBradbury @sompylasarãŸã èå³ãããå Žåã¯ãããŒãã«ã¿ã°ã䜿çšããŠãŠã£ã³ããŠåŠçãè¡ãããšãã§ããŸããã å®éãreact-windowãã©ããããã©ã€ãã©ãªãäœæããããšã«ãªããŸããã ããã§ã©ã€ããã¢ãèŠãããšãã§ããŸãïŒ https ïŒ
ããŒãã«ã¿ã°ã欲ããã£ãã®ã¯ãäž»ã«ã¹ã¿ã€ãªã³ã°ã®ããã§ããã éåžžã®htmlããŒãã«ã®ã¹ã¿ã€ãªã³ã°ã¯tw-bootstrapã䜿çšãããšéåžžã«ç°¡åãªã®ã§ããŠã£ã³ããŠããŒãã«ã§ãåãããšãããããšæããŸããã
ç§ã¯ãã©ã€ã¢ã³ã«ã¿ã°ãä»ããŠããã®å®è£ ã«ã€ããŠã©ãæããå°ããããªããŸãïŒåœŒã¯htmlããŒãã«ã¿ã°ãæ©èœããªããšèšã£ãã®ã§ïŒã ãããã圌ã¯ãã§ã«ç§ãååã«å©ããŠãããŸããã ã ããç§ã¯ããªããã¡ã«ãããä»»ããŸãã
ããããšãããããŸããã
ããã¯èå³æ·±ãã¢ãããŒã@pupuduã§ãã ããããŒãšè¡ã«å¥ã
ã®<table>
ã¿ã°ãä»ããããšã§ã¢ã¯ã»ã·ããªãã£ã®æžå¿µããããã©ããã¯ããããŸããããããã§ãªãå Žåã¯é©åãªã¢ã€ãã¢ã§ãã
react-datasheet
ãreact-window
ãšäžç·ã«äœ¿çšããããšããŠããŸãããåºæ¬çã«ã¯æ©èœããŸãã
function sheetRenderer(props) {
const Row = ({ index, style }) => (
React.cloneElement(props.children[index], { style })
);
return (
<table className={props.className}>
<tbody>
<FixedSizeList
height={150}
itemCount={1000}
itemSize={35}
width={300}
>
{Row}
</FixedSizeList>
</tbody>
</table>
)
}
export default function EntityTable(props: IEntityTableProps) {
const initialGrid = useMemo(() => {
return getTableGridFromCSV(props.entityListCSV);
}, [props.entityListCSV]);
const [modifiedGrid, updateModifiedGrid] = useImmer(initialGrid);
return (
<ReactDataSheet
data={modifiedGrid}
sheetRenderer={sheetRenderer}
valueRenderer={cell => cell.value}
onCellsChanged={changes => {
updateModifiedGrid(draft => {
changes.forEach(({ cell, row, col, value }) => {
draft[row][col].value = value || '';
});
});
}}
/>
);
}
function getTableGridFromCSV(csv: string) {
return csv.split('\n').map(row =>
row.split(',').map((cell, index) => {
if (index === 0) {
return {
value: cell,
forceComponent: true,
component: <button onClick={() => console.log(cell)}>{cell}</button>,
};
}
if (index === 2) {
return {
value: cell,
};
}
return {
value: cell,
component: <span>{cell}</span>,
};
}),
);
}
ã¬ã³ããªã³ã°ãããŸããå¯äžã®åé¡ã¯Warning: validateDOMNesting(...): <tr> cannot appear as a child of <div>.
index.js:1437 Warning: validateDOMNesting(...): <div> cannot appear as a child of <tbody>.
ãããç§ã¯React-Tableã§ãããè©ŠããŠããŸãããããŒãã«èŠçŽ ã®ä»£ããã«divã䜿çšããå¿ èŠãããããšã«æ°ã¥ããŸããã ããã«é¢ããåé¡ã¯ãmaterial / bootstrapã®ãããªã¹ã¿ã€ãªã³ã°ã©ã€ãã©ãªããããã®èŠçŽ ã«äŸåããŠããããšã§ãã ãããã£ãŠãããŒãã«ã¹ããŒããããŒãã«èŠçŽ ã§ã¯ãªãdivã«å€æŽããã®ã¯ã¯ããã«æéãããããŸãã ããŒãã«èŠçŽ ã䜿çšããŠå·®åããšãããšã¯å¯èœã§ããããããšãä»ããç¬èªã®ã¹ã¿ã€ã«ãäœæããå¿ èŠããããŸããïŒ
@simkessyãã§ã«æ°ã¥ããŠããªãéãããŠã£ã³ããŠããŒãã«ããã§ãã¯ã¢ãŠãããå¿
èŠããããŸãã htmlããŒãã«ã¿ã°ã䜿çšã§ãããããæ¢åã®ã¹ã¿ã€ã«ãåå©çšã§ããŸãã ãã ããããŒãã«ã¯react-tableã»ã©é«åºŠã§ã¯ãªãããšãèªããå¿
èŠããããŸãã
https://window-table.netlify.com/
@pupuduç§ã¯ããªãã®ãªãŒãã³ãœãŒã¹ã®åªåã
éåžžã«å°ããªã³ãŒããšå€ãã®åµé æ§ã§ãããå®çŸããããšãã§ããããšãããããŸããã ã³ãŒãã¯éåžžã«åçŽãªã®ã§ã誰ã§ãã³ããŒ/貌ãä»ãããŠå¥œã¿ã«åãããŠæ¡åŒµã§ããŸãã @bvaughnã¯ãæ¹æ³ãç解ããåŸãå¿ èŠã«å¿ããŠã©ã€ãã©ãªã«è¿œå ããã®ã¯éåžžã«ç°¡åã§ãããæ¹æ³ãç¥ã£ãŠããå Žåã¯ãªãŒããŒã©ã€ãããã®ãéåžžã«ç°¡åã§ãã
ããã®äžè¶³ïŒ
äœæ¥ã³ãŒããµã³ãããã¯ã¹ïŒ https ïŒ
åç §çšã³ãŒã
import React from 'react'
import { useState, useRef, useContext } from 'react'
import { FixedSizeList, FixedSizeListProps } from 'react-window'
import { render } from 'react-dom'
/** Context for cross component communication */
const VirtualTableContext = React.createContext<{
top: number
setTop: (top: number) => void
header: React.ReactNode
footer: React.ReactNode
}>({
top: 0,
setTop: (value: number) => {},
header: <></>,
footer: <></>,
})
/** The virtual table. It basically accepts all of the same params as the original FixedSizeList.*/
function VirtualTable({
row,
header,
footer,
...rest
}: {
header?: React.ReactNode
footer?: React.ReactNode
row: FixedSizeListProps['children']
} & Omit<FixedSizeListProps, 'children' | 'innerElementType'>) {
const listRef = useRef<FixedSizeList | null>()
const [top, setTop] = useState(0)
return (
<VirtualTableContext.Provider value={{ top, setTop, header, footer }}>
<FixedSizeList
{...rest}
innerElementType={Inner}
onItemsRendered={props => {
const style =
listRef.current &&
// @ts-ignore private method access
listRef.current._getItemStyle(props.overscanStartIndex)
setTop((style && style.top) || 0)
// Call the original callback
rest.onItemsRendered && rest.onItemsRendered(props)
}}
ref={el => (listRef.current = el)}
>
{row}
</FixedSizeList>
</VirtualTableContext.Provider>
)
}
/** The Row component. This should be a table row, and noted that we don't use the style that regular `react-window` examples pass in.*/
function Row({ index }: { index: number }) {
return (
<tr>
{/** Make sure your table rows are the same height as what you passed into the list... */}
<td style={{ height: '36px' }}>Row {index}</td>
<td>Col 2</td>
<td>Col 3</td>
<td>Col 4</td>
</tr>
)
}
/**
* The Inner component of the virtual list. This is the "Magic".
* Capture what would have been the top elements position and apply it to the table.
* Other than that, render an optional header and footer.
**/
const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
function Inner({ children, ...rest }, ref) {
const { header, footer, top } = useContext(VirtualTableContext)
return (
<div {...rest} ref={ref}>
<table style={{ top, position: 'absolute', width: '100%' }}>
{header}
<tbody>{children}</tbody>
{footer}
</table>
</div>
)
}
)
/**
* Render Our Example
**/
render(
<VirtualTable
height={300}
width="100%"
itemCount={1000}
itemSize={36}
header={
<thead>
<tr>
<th>Index</th>
<th>Header 2</th>
<th>Header 3</th>
<th>Header 4</th>
</tr>
</thead>
}
row={Row}
footer={
<tfoot>
<tr>
<td>Footer 1</td>
<td>Footer 2</td>
<td>Footer 3</td>
<td>Footer 4</td>
</tr>
</tfoot>
}
/>,
document.querySelector('main')
)
@jamesmfriedmanã¢ãããŒãã倧奜ãã§ãã ãããéæããããã«ã³ã³ããã¹ãã䜿çšããããã®æ¬åœã«èå³æ·±ãã¢ã€ãã¢ã ããããŒçšãšããã£çšã®2ã€ãã¬ã³ããªã³ã°ããç§ã®ã¢ãããŒããšã¯ç°ãªããããŒãã«ã1ã€ã ãã¬ã³ããªã³ã°ãããšããäºå®ãæ°ã«å ¥ã£ãŠããŸãã ããã¯ããŠã£ã³ããŠããŒãã«ã®ãŠãŒã¶ãŒã«å€ãã®æ··ä¹±ãåŒãèµ·ãããŸããïŒãããæ¥ãã®ãèŠãŠããŸããã§ããïŒã
ãããããã°ããããã®ã¢ã€ãã¢ããŠã£ã³ããŠããŒãã«ã§äœ¿çšããŠã¿ãŸãã æ倧ã®èª²é¡ã¯ãã³ã³ãã³ãã«åºã¥ããŠè¡ã®ãµã€ãºãèªååããæ¹æ³ãèŠã€ããããšã ãšæããŸãïŒããã¯ãå°ãªããšãwindo-tableã®æ倧ã®èª²é¡ã§ããïŒã
éåžžã«ææã«èŠãã@jamesmfriedman ã @bvaughnãã®ã¢ãããŒãã«ã€ããŠäœãæžå¿µã¯ãããŸããïŒ
@jamesmfriedmanããããŒãã³ã³ãã³ããšäžç·ã«äžã«ã¹ã¯ããŒã«ããããã§ãã ã¹ãã€ãããšã¯ã§ããŸããïŒ
å®éã«ã¯å¯èœã§ããããã®å®è£ ã«åºæã®ãã®ã§ã¯ãããŸããã HTMLããŒãã«èŠçŽ ã䜿çšããŠã¹ãã£ãããŒããããŒãã°ãŒã°ã«ã§æ€çŽ¢ããã ãã§ãã ãããè¡ãæ¹æ³ã¯ãå®éã«ã¯THèŠçŽ ã®äœçœ®ãåºå®ããããšã§ãããšæŒ ç¶ãšæãåºããŸãã
ã¹ãã£ãããŒãããã®ðããã¯å€ããããã«@marinkå©ããããªãäŸãã°@jamesmfriedmanãããã§ããããã¯äžäŸã§ãhttps://codesandbox.io/s/react-window-with-table-elements-jj70eããªããè¿œå ããå¿
èŠãstyle={{ position: 'sticky', top: 0 }}>
ããth
ã¿ã°
@jamesmfriedmanäŸãããããšãã ç§ã¯ããã䜿çšããããšãæ€èšããã€ããã§ãã ãããã topãåèšç®ããŠããŒãã«èŠçŽ ã«çµ¶å¯Ÿäœçœ®ãèšå®ãã代ããã«ã
ãããã£ãŠã79è¡ç®ã¯<table style={{ top: 0, position: 'sticky', width: '100%' }}>
ããã«ãããäžçªäžã«ãããšãã«ã¹ã¯ããŒã«ãç¶ããå Žåã®ã¹ã¯ããŒã«ã®åé¡ãä¿®æ£ãããŸãã
HTMLããŒãã«ã䜿çšãããã1ã€ã®çç±ã¯ãIE11ããµããŒãããããšã§ãã FixedSizeList
ã䜿çšããŠãCSSã°ãªããã§ã¹ã¿ã€ã«ãèšå®ããŠããŸãã ãã ããã¬ã¹ãã³ã·ãåããµã€ãºã®ç°ãªãåãªã©ã®ä»ã®æ©èœãè¿œå ãããã¹ãŠãIE11ãšé£æºãããå¿
èŠãããå Žåã¯ã倧éã®ã³ãŒããå¿
èŠã«ãªããŸãã HTMLããŒãã«ã¯ããã©ã«ãã§ã³ãŒããªãã§æ©èœããŸãã
IE11ã¯ãããµããŒããã¹ããã®ã§ã¯ãããŸãã:)
ãã¹ãŠã®FEéçºè ã¯ãIE11ã®æ»ãæãã§ããŸãã ããããæ®å¿µãªãããç§ãã¡ãæ³åããããšããã§ããªãçç±ã®ããã«è¡åãèµ·ããããšãã§ããªããããã«åºå·ããŠããäŒæ¥/人ã ãããŸãã ããŸãããã°ãããã¯ã»ãã®æ°å¹Žå ã®ããšã§ãã ãããŸã§ã¯ã奜ããšå¥œãŸãããšã«ããããããIE11ããµããŒãããå¿ èŠããããŸãã
ç§ã«ãšã£ãŠã飲ã¿èŸŒãã®ã¯é£ããè¬ã§ããã
@ olafur164é«éã¹ã¯ããŒã«ã§ã¹ãã£ãããŒããããŒãå£ããªãããã«ä¿®æ£ããŠããããŸãã ã¹ã ãŒãºã«å察ããããã«äžåºŠã«1è¡ãã€ã¹ã¯ããŒã«ããã®ã§ããã¹ãã£ãããŒããªå€èŠ³ãç¶æããæ¹æ³ããããã©ããç¥ã£ãŠããŸããïŒ
ç§ã®çµéšãreact-virtualized ïŒ react-windowã®åé¡ããŒãžã§ãïŒãšåãåé¡ãçºçããmaterial-tableãšåŒã°ããããã€ãã®ãããªã¢ã«UIã©ã€ãã©ãªïŒä»®æ³åãšããŒãã«èŠçŽ ã®çµã¿åããïŒã§å
±æããŸãããïŒ https ïŒ validateDOMNesting(...)
èŠåãªã©ããŸã ããã€ãã®åé¡ããããŸãã
@jamesmfriedmanã¯ããªãã®äŸã«æè¬ããŸãðããã¯å€§ãã«åœ¹ç«ã¡ãŸãã
th
ã¿ã°ã«style={{ position: 'sticky', top: 0 }}>
ãè¿œå ããå¿ èŠããããŸã
@JCofmanãããCSSä¿®æ£ãè©ŠããŸããããæ©èœããŸããã ã³ãŒããµã³ãããã¯ã¹ã®äŸã¯æ¬¡ã®ãšããã§ã-httpsïŒ//codesandbox.io/s/react-window-with-table-elements-forked-huti6ïŒfile = / src / index.tsxïŒ514-542
2ã€ã®åé¡ããããŸã-
åãã£ãŠæè¬ããŸã ïŒïŒ
@jamesmfriedmanã¢ãããŒãã倧奜ãã§ãã ãããéæããããã«ã³ã³ããã¹ãã䜿çšããããã®æ¬åœã«èå³æ·±ãã¢ã€ãã¢ã ããããŒçšãšããã£çšã®2ã€ãã¬ã³ããªã³ã°ããç§ã®ã¢ãããŒããšã¯ç°ãªããããŒãã«ã1ã€ã ãã¬ã³ããªã³ã°ãããšããäºå®ãæ°ã«å ¥ã£ãŠããŸãã ããã¯ããŠã£ã³ããŠããŒãã«ã®ãŠãŒã¶ãŒã«å€ãã®æ··ä¹±ãåŒãèµ·ãããŸããïŒãããæ¥ãã®ãèŠãŠããŸããã§ããïŒã
ãããããã°ããããã®ã¢ã€ãã¢ããŠã£ã³ããŠããŒãã«ã§äœ¿çšããŠã¿ãŸãã æ倧ã®èª²é¡ã¯ãã³ã³ãã³ãã«åºã¥ããŠè¡ã®ãµã€ãºãèªååããæ¹æ³ãèŠã€ããããšã ãšæããŸãïŒããã¯ãå°ãªããšãwindo-tableã®æ倧ã®èª²é¡ã§ããïŒã
è¡ã«display: contents
ã䜿çšããŠdisplay: grid
ã䜿çšããŠãããããéåžžã«ãã䌌ã解決çãèŠã€ããããšã«ãªããŸããããããã£ãŠãåºæ¬çã«table > tr
èŠçŽ ã®å¶çŽã«åŸããŸãã
context + refsã䜿çšããŠå éšã¡ãœãããåŒã³åºããŸããããæåã®åã®style.topå€ãæ€çŽ¢ããããšã§åãããšãã§ãããããããã¯ãŸã£ããäžèŠã§ãã
const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>(
function Inner({ children, ...rest }, ref) {
const { header, footer } = useContext(VirtualTableContext)
const {style} = children[0].props;
return (
<div {...rest} ref={ref}>
<table style={style}>
{header}
<tbody>{children}</tbody>
{footer}
</table>
</div>
)
}
)
ã¹ã¿ã€ã«ããããã¯ãåè¡ã«å¯ŸããŠcreateElementãå®è¡ãããšãã«ã©ã€ãã©ãªã«ãã£ãŠæäŸãããç¹å®ã®Row
ã³ã³ããŒãã³ãã¯style
ãtr
ã«å²ãåœãŠãªããããããã§ã¯ãããŸãããã©ã¡ãããæž¡ããŸãã
æè¿ããããªããšãèããŠããŸããã cssã«ã¹ã¿ã ããããã£ãä»ããŠç䌌èŠçŽ ïŒåŸ/åïŒã䜿çšããŠããã£ã³ã°ã§ããŒãã«æ¬äœå šäœã移åãããšã©ããªããŸããð€
åå¿ä»®æ³ã䜿çšããäŸã§ã¯ã httpsïŒ//codesandbox.io/s/poc-react-virtual-table-jyz0mã«ãªã
å¿
èŠãªUXãå®çŸããããã«ããŒãã«ã絶察ã«å¿
èŠã§ãããã react-window
ã§æ©èœãããããã®åé¿çã«æºè¶³ã§ããŸãã
çµå±ãç§ã¯èªåã§ä»®æ³åããžãã¯ãããã¯ã«æœåºãã2ã€ã®ããŒãã«ã䜿çšããŠå®è£ ããŸããã1ã€ã¯ããããŒçšã§ããã1ã€ã¯ã³ã³ãã³ãçšã§ãã ç§ã®ã¢ãããŒãã®éãã¯ã2çªç®ã®ããŒãã«ã«ã¯ãŸã ããŒã¯ã¢ããã«ããããŒããããŸãããã¢ã¯ã»ã¹å¯èœãªãŸãŸã§ããããã«èŠèŠçã«é衚瀺ã«ãªã£ãŠããã®ã«å¯Ÿããæåã®ããŒãã«ã®ããããŒã¯ç®ã®èŠãããŠãŒã¶ãŒã®ããã ãã«ãããäœçœ®çã«åºå®ãããŠããŸãããã³ãŒãã¯å€§å¹ ã«åçŽåãããŸããã
誰ãããããè©Šãããå Žåã«åããŠããããæšãŠãã ãã§ãã
@piecykããã¯çŽ æŽããããã®ã§ãvirtuosoã®å®è£ æ¹æ³ãšéåžžã«ãã䌌ãŠããŸãïŒ https ïŒ //virtuoso.dev/grouped-by-first-letter/
ã³ã³ããå šäœãabsolute / topã§é 眮ããããšã¯ããã©ãŒãã³ã¹ãé«ãããšãè¿œå ããå¿ èŠããããŸãããChromeã§ããã©ãŒãã³ã¹ç£æ»ãå®è¡ãããšãFPSã«åœ±é¿ãäžããå¯èœæ§ã®ããCLSã®åé¡ãçºçããŸãã 圱é¿ã¯ç®ç«ããªããšæããŸãããã®äŸã§ã¯ã https ïŒ
ç§ã¯ãããèªåã§è©Šã¿ãŠãè¿ããã¡ã«éãã枬å®ããŸãã
@pupuduç§ã¯ããªãã®ãªãŒãã³ãœãŒã¹ã®åªåã
éåžžã«å°ããªã³ãŒããšå€ãã®åµé æ§ã§ãããå®çŸããããšãã§ããããšãããããŸããã ã³ãŒãã¯éåžžã«åçŽãªã®ã§ã誰ã§ãã³ããŒ/貌ãä»ãããŠå¥œã¿ã«åãããŠæ¡åŒµã§ããŸãã @bvaughnã¯ãæ¹æ³ãç解ããåŸãå¿ èŠã«å¿ããŠã©ã€ãã©ãªã«è¿œå ããã®ã¯éåžžã«ç°¡åã§ãããæ¹æ³ãç¥ã£ãŠããå Žåã¯ãªãŒããŒã©ã€ãããã®ãéåžžã«ç°¡åã§ãã
_ããã®äžè¶³_ïŒ
- ã¬ã³ããªã³ã°åŸã®æåã®è¡ã®ãããããã¹ã¿ã€ã«ããã£ããã£ããŸã
- ãã®å€ãReact.Contextã«ä¿åããŠãæž¡ããããã«ããŸã
- è¡èªäœã§ã¯ãªãã移åãããããŒãã«ã³ã³ããŒãã³ãã«å€ãé©çšããŸã
- ããããŒãããã¿ãŒãªã©ã®ã¹ããããè¿œå ããŸãã
- ã©ã€ãã©ãªã®äººéå·¥åŠã§ã¯ç©äºããã¡ããšæž¡ãããšãã§ããªããããReact.Contextã¯ã³ã³ããŒãã³ãéã®ã³ãã¥ãã±ãŒã·ã§ã³ãå æããããã®ããŒããŒã§ãã
äœæ¥ã³ãŒããµã³ãããã¯ã¹ïŒ https ïŒ
åç §çšã³ãŒã
import React from 'react' import { useState, useRef, useContext } from 'react' import { FixedSizeList, FixedSizeListProps } from 'react-window' import { render } from 'react-dom' /** Context for cross component communication */ const VirtualTableContext = React.createContext<{ top: number setTop: (top: number) => void header: React.ReactNode footer: React.ReactNode }>({ top: 0, setTop: (value: number) => {}, header: <></>, footer: <></>, }) /** The virtual table. It basically accepts all of the same params as the original FixedSizeList.*/ function VirtualTable({ row, header, footer, ...rest }: { header?: React.ReactNode footer?: React.ReactNode row: FixedSizeListProps['children'] } & Omit<FixedSizeListProps, 'children' | 'innerElementType'>) { const listRef = useRef<FixedSizeList | null>() const [top, setTop] = useState(0) return ( <VirtualTableContext.Provider value={{ top, setTop, header, footer }}> <FixedSizeList {...rest} innerElementType={Inner} onItemsRendered={props => { const style = listRef.current && // @ts-ignore private method access listRef.current._getItemStyle(props.overscanStartIndex) setTop((style && style.top) || 0) // Call the original callback rest.onItemsRendered && rest.onItemsRendered(props) }} ref={el => (listRef.current = el)} > {row} </FixedSizeList> </VirtualTableContext.Provider> ) } /** The Row component. This should be a table row, and noted that we don't use the style that regular `react-window` examples pass in.*/ function Row({ index }: { index: number }) { return ( <tr> {/** Make sure your table rows are the same height as what you passed into the list... */} <td style={{ height: '36px' }}>Row {index}</td> <td>Col 2</td> <td>Col 3</td> <td>Col 4</td> </tr> ) } /** * The Inner component of the virtual list. This is the "Magic". * Capture what would have been the top elements position and apply it to the table. * Other than that, render an optional header and footer. **/ const Inner = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement>>( function Inner({ children, ...rest }, ref) { const { header, footer, top } = useContext(VirtualTableContext) return ( <div {...rest} ref={ref}> <table style={{ top, position: 'absolute', width: '100%' }}> {header} <tbody>{children}</tbody> {footer} </table> </div> ) } ) /** * Render Our Example **/ render( <VirtualTable height={300} width="100%" itemCount={1000} itemSize={36} header={ <thead> <tr> <th>Index</th> <th>Header 2</th> <th>Header 3</th> <th>Header 4</th> </tr> </thead> } row={Row} footer={ <tfoot> <tr> <td>Footer 1</td> <td>Footer 2</td> <td>Footer 3</td> <td>Footer 4</td> </tr> </tfoot> } />, document.querySelector('main') )
ãããããããšãã誰ãããããInfiniteLoader
ã³ã³ããŒãã³ãã§ïŒæåããŠïŒäœ¿çšããããšããŸãããïŒ...ç§ã¯ããã蹎ã£ãŠã¿ãŸããããå
åŽã®ãã©ãããŒãã«åé¡ããããŸããç¡éããŒããŒãäºæããªãå°éå
·ãinnerElementTypeã«æž¡ããŠããããã ãšæããŸãã
æãåèã«ãªãã³ã¡ã³ã
@pupuduç§ã¯ããªãã®ãªãŒãã³ãœãŒã¹ã®åªåã
éåžžã«å°ããªã³ãŒããšå€ãã®åµé æ§ã§ãããå®çŸããããšãã§ããããšãããããŸããã ã³ãŒãã¯éåžžã«åçŽãªã®ã§ã誰ã§ãã³ããŒ/貌ãä»ãããŠå¥œã¿ã«åãããŠæ¡åŒµã§ããŸãã @bvaughnã¯ãæ¹æ³ãç解ããåŸãå¿ èŠã«å¿ããŠã©ã€ãã©ãªã«è¿œå ããã®ã¯éåžžã«ç°¡åã§ãããæ¹æ³ãç¥ã£ãŠããå Žåã¯ãªãŒããŒã©ã€ãããã®ãéåžžã«ç°¡åã§ãã
ããã®äžè¶³ïŒ
äœæ¥ã³ãŒããµã³ãããã¯ã¹ïŒ https ïŒ
åç §çšã³ãŒã