Skip to content

Commit 6142a59

Browse files
committed
fix(lifecycle): need to handle mount and remount
aka create a new grid with each mount
1 parent 0f3766b commit 6142a59

File tree

6 files changed

+78
-62
lines changed

6 files changed

+78
-62
lines changed

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "grid-react-adapter",
33
"version": "1.0.0",
4-
"main": "dist/main.js",
4+
"main": "dist/lib/index.js",
55
"typings": "dist/lib/index.d.ts",
66
"scripts": {
77
"commitmsg": "validate-commit-msg",
@@ -23,7 +23,7 @@
2323
"prebuild": "npm run clean && npm run test",
2424
"build": "node tools/build.js",
2525
"prebuild:lib": "npm run prebuild",
26-
"build:lib": "node tools/buildLib.js",
26+
"build:lib": "echo 'built'",
2727
"build:lib:watch": "node tools/buildLib.js --watch",
2828
"build:server": "npm run build && npm run open:dist",
2929
"test": "jest --config jest.single.config.js",
@@ -58,8 +58,8 @@
5858
"copy-webpack-plugin": "~3.0.1",
5959
"css-loader": "^0.28.7",
6060
"ejs-compiled-loader": "~3.1.0",
61-
"enzyme": "^3.1.1",
62-
"enzyme-adapter-react-16": "^1.0.4",
61+
"enzyme": "^3.11.0",
62+
"enzyme-adapter-react-16": "^1.15.0",
6363
"html-webpack-plugin": "~4.5.2",
6464
"husky": "^0.14.3",
6565
"jest": "~26.6.3",

src/lib/components/__tests__/grid.test.tsx

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const mockGridCreate = jest.fn((o: any) => ({
5757
}));
5858
(grid.create as any) = mockGridCreate;
5959

60-
import { mount, shallow } from 'enzyme';
60+
import { mount } from 'enzyme';
6161
import { ReactGrid } from '../grid';
6262

6363
beforeEach(() => {
@@ -77,13 +77,6 @@ beforeEach(() => {
7777
mockReactDomRender.mockClear();
7878
});
7979

80-
it('should render', () => {
81-
const reactGrid = shallow(
82-
<ReactGrid rows={[]} cols={[]} />
83-
);
84-
expect(reactGrid).toMatchElement(<div />);
85-
});
86-
8780
it('should create a container for the grid', () => {
8881
const reactGrid = mount(
8982
<ReactGrid rows={[]} cols={[]} />
@@ -109,23 +102,23 @@ it('should keep the container in the DOM on subsequent updates', () => {
109102
});
110103

111104
it('should create a grid with opts', () => {
112-
const reactGrid = shallow(
105+
const reactGrid = mount(
113106
<ReactGrid rows={[]} cols={[]} snapToCell={true} />
114107
);
115108
expect(mockGridCreate).toHaveBeenCalledWith({ snapToCell: true });
116109
});
117110

118111
it('should build a grid with the container', () => {
119-
const reactGrid = shallow(
112+
const reactGrid = mount(
120113
<ReactGrid rows={[]} cols={[]} />
121114
);
122-
expect(mockGridBuild).toHaveBeenCalledWith((reactGrid.instance() as ReactGrid).gridContainer);
115+
expect(mockGridBuild).toHaveBeenCalledWith((reactGrid.instance() as ReactGrid).gridContainer.current);
123116
});
124117

125118
it('should add the supplied rows and cols to the grid', () => {
126119
const rows = [{ header: true }, { height: 4 }];
127120
const cols = [{ fixed: true }, { width: 4 }];
128-
const reactGrid = shallow(
121+
const reactGrid = mount(
129122
<ReactGrid rows={rows} cols={cols} />
130123
);
131124
expect(mockRowDim.rowColModel.add.mock.calls[0][0]).toMatchObject(rows);
@@ -135,7 +128,7 @@ it('should add the supplied rows and cols to the grid', () => {
135128
it('should not call add if the supplied rows and cols havent changed functionally', () => {
136129
const rows = [{ header: true }, { height: 4 }];
137130
const cols = [{ fixed: true }, { width: 4 }];
138-
const reactGrid = shallow(
131+
const reactGrid = mount(
139132
<ReactGrid rows={rows} cols={cols} />
140133
);
141134
mockRowDim.rowColModel.add.mockClear();
@@ -151,7 +144,7 @@ it('should not call add if the supplied rows and cols havent changed functionall
151144
it('should not call add if the supplied rows and cols havent changed ref', () => {
152145
const rows = [{ header: true }, { height: 4 }];
153146
const cols = [{ fixed: true }, { width: 4 }];
154-
const reactGrid = shallow(
147+
const reactGrid = mount(
155148
<ReactGrid rows={rows} cols={cols} />
156149
);
157150
mockRowDim.rowColModel.add.mockClear();
@@ -167,7 +160,7 @@ it('should not call add if the supplied rows and cols havent changed ref', () =>
167160
it('should supply data to the grid', () => {
168161
const dataRow1 = [{ value: undefined, formatted: '1' }, { value: undefined, formatted: '2' }];
169162
const dataRow2 = [{ value: undefined, formatted: '3' }, { value: undefined, formatted: '4' }];
170-
const reactGrid = shallow(
163+
const reactGrid = mount(
171164
<ReactGrid
172165
rows={[{}, {}]}
173166
cols={[{}, {}]}
@@ -188,7 +181,7 @@ it('should re-supply data to the grid IFF the ref has changed', () => {
188181
const dataRow2 = [{ value: undefined, formatted: '3' }, { value: undefined, formatted: '4' }];
189182
const rows = [{}, {}];
190183
const cols = [{}, {}];
191-
const reactGrid = shallow(
184+
const reactGrid = mount(
192185
<ReactGrid
193186
rows={rows}
194187
cols={cols}

src/lib/components/grid.tsx

Lines changed: 60 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -32,42 +32,44 @@ export interface IGridProps extends IGridOpts {
3232
export interface IGridState { }
3333

3434
export class ReactGrid extends Component<IGridProps, IGridState> {
35-
grid: Grid;
35+
grid: Grid | undefined;
3636
cellRendererBuilder: IRowColBuilder | undefined;
3737
headerCellRendererBuilder: IRowColBuilder | undefined;
38-
gridContainer: HTMLElement;
39-
reactContainer: HTMLElement | null;
38+
gridContainer: React.RefObject<HTMLDivElement>;
4039

4140
constructor(props: IGridProps) {
4241
super(props);
43-
this.gridContainer = document.createElement('div');
44-
this.gridContainer.style.position = 'absolute';
45-
this.gridContainer.style.top = '0';
46-
this.gridContainer.style.left = '0';
47-
this.gridContainer.style.height = '100%';
48-
this.gridContainer.style.width = '100%';
42+
this.gridContainer = React.createRef();
43+
}
44+
45+
private createGrid() {
4946
const { rows, cols, data, ...gridOpts } = this.props;
50-
this.grid = create(gridOpts);
51-
const origSet = this.grid.dataModel.set;
52-
this.grid.dataModel.set = (rowOrData: number | Array<IGridDataChange<any>>, c?: number, datum?: string | string[]) => {
47+
const grid = create(gridOpts);
48+
this.grid = grid;
49+
const origSet = grid.dataModel.set;
50+
grid.dataModel.set = (rowOrData: number | Array<IGridDataChange<any>>, c?: number, datum?: string | string[]) => {
5351
const dataChanges = !Array.isArray(rowOrData)
5452
? [{
5553
row: rowOrData,
5654
col: c as number,
5755
value: datum
58-
5956
}]
6057
: rowOrData;
6158

6259
const newChanges = this.props.setData && this.props.setData(dataChanges) || dataChanges;
63-
origSet.call(this.grid.dataModel, newChanges);
60+
origSet.call(grid.dataModel, newChanges);
6461
};
62+
return grid
6563
}
6664

6765
ensureGridContainerInDOM() {
68-
if (this.reactContainer && this.reactContainer.firstChild !== this.gridContainer) {
69-
this.reactContainer.appendChild(this.gridContainer);
66+
const grid = this.grid || this.createGrid();
67+
if (this.gridContainer.current) {
68+
grid.build(this.gridContainer.current);
69+
} else {
70+
console.error('grid ref didnt exist at mount')
7071
}
72+
return grid;
7173
}
7274

7375
createDiscriptors(
@@ -121,19 +123,19 @@ export class ReactGrid extends Component<IGridProps, IGridState> {
121123
d1.some((descriptor, index) => JSON.stringify(d2[index]) !== JSON.stringify(descriptor));
122124
}
123125

124-
handleNewData(data: Array<Array<IGridDataResult<any>>> | undefined) {
126+
handleNewData(data: Array<Array<IGridDataResult<any>>> | undefined, grid: Grid) {
125127
if (data) {
126128
data.forEach((row, dataRowIndex) => {
127-
this.grid.rows.converters.data.get(dataRowIndex).data = row;
129+
grid.rows.converters.data.get(dataRowIndex).data = row;
128130
});
129-
this.grid.dataModel.handleCachedDataChange();
131+
grid.dataModel.handleCachedDataChange();
130132
}
131133
}
132134

133135
componentDidMount() {
134-
this.ensureGridContainerInDOM();
135-
this.grid.build(this.gridContainer);
136-
this.cellRendererBuilder = this.grid.colModel.createBuilder(
136+
console.log('mount')
137+
const grid = this.ensureGridContainerInDOM();
138+
this.cellRendererBuilder = grid.colModel.createBuilder(
137139
() => document.createElement('div'),
138140
(element, context) => {
139141
const rendered = this.props.cellRenderer && this.props.cellRenderer(context);
@@ -145,11 +147,11 @@ export class ReactGrid extends Component<IGridProps, IGridState> {
145147
}
146148
);
147149

148-
this.headerCellRendererBuilder = this.grid.rowModel.createBuilder(
150+
this.headerCellRendererBuilder = grid.rowModel.createBuilder(
149151
() => document.createElement('div'),
150152
(element, context) => {
151153
const { virtualRow } = context;
152-
if (virtualRow >= this.grid.rows.rowColModel.numHeaders()) {
154+
if (virtualRow >= grid.rows.rowColModel.numHeaders()) {
153155
return undefined;
154156
}
155157
const rendered = this.props.headerCellRenderer && this.props.headerCellRenderer(context);
@@ -160,35 +162,55 @@ export class ReactGrid extends Component<IGridProps, IGridState> {
160162
return element;
161163
}
162164
);
163-
this.reflectNewRowsOrCols(this.props.rows, this.grid.rows);
164-
this.reflectNewRowsOrCols(this.props.cols, this.grid.cols);
165-
this.handleNewData(this.props.data);
165+
this.reflectNewRowsOrCols(this.props.rows, grid.rows);
166+
this.reflectNewRowsOrCols(this.props.cols, grid.cols);
167+
this.handleNewData(this.props.data, grid);
166168
}
167169

168170
// we return false from should update but react may ignore our hint in the future
169-
componentDidUpdate(prevProps : IGridProps) {
170-
this.ensureGridContainerInDOM();
171+
componentDidUpdate(prevProps: IGridProps) {
172+
console.log('update')
173+
const something = 'a string you cant ignore';
171174

172-
const nextProps = this.props;
175+
const grid = this.ensureGridContainerInDOM();
176+
177+
const nextProps = this.props;
173178
if (this.descriptorsChanged(prevProps.rows, nextProps.rows)) {
174-
this.reflectNewRowsOrCols(nextProps.rows, this.grid.rows);
179+
this.reflectNewRowsOrCols(nextProps.rows, grid.rows);
175180
}
176181
if (this.descriptorsChanged(prevProps.cols, nextProps.cols)) {
177-
this.reflectNewRowsOrCols(nextProps.cols, this.grid.cols);
182+
this.reflectNewRowsOrCols(nextProps.cols, grid.cols);
178183
}
179184

180185
if (prevProps.data !== nextProps.data) {
181-
this.handleNewData(nextProps.data);
186+
this.handleNewData(nextProps.data, grid);
182187
}
183188
}
184-
185-
componentWillUnmount(){
186-
this.grid.destroy();
189+
190+
componentWillUnmount() {
191+
console.log('unmount')
192+
if(this.grid){
193+
this.grid.destroy();
194+
this.grid.destroyed = true;
195+
this.grid = undefined;
196+
}
187197
}
188198

189199
render() {
200+
201+
190202
return (
191-
<div ref={(elem) => { this.reactContainer = elem; }} />
203+
<div>
204+
<div ref={this.gridContainer} style={gridStyle} />
205+
</div>
192206
);
193207
}
194-
}
208+
}
209+
210+
const gridStyle = {
211+
position: 'absolute',
212+
top: '0',
213+
left: '0',
214+
height: '100%',
215+
width: '100%',
216+
} as const

tools/buildLib.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const webpackInstance = webpack(
2323
createConfig({
2424
demo: false,
2525
branchName,
26-
isLibrary: true
26+
isLibrary: true,
2727
})
2828
);
2929

webpack/webpack.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,8 @@ module.exports = (opts) => {
201201

202202
// webpack config object
203203
const config = {
204-
mode : isDev ? 'development' : 'production',
204+
// mode : isDev ? 'development' : 'production',
205+
mode : 'development',
205206
resolve: {
206207
extensions: ['.js', '.ts', '.tsx'],
207208
alias: aliases

0 commit comments

Comments
 (0)