Skip to content

Commit dce35ad

Browse files
authored
Merge pull request #64 from GamgeeNL/master
Refactored componentWillUpdate into getDerivedStateFromProps
2 parents 1c7e7fa + 2ef3161 commit dce35ad

1 file changed

Lines changed: 94 additions & 84 deletions

File tree

src/index.js

Lines changed: 94 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,60 @@
1-
import React, { PureComponent } from 'react'
2-
import { Image as RNImage } from 'react-native'
3-
import PropTypes from 'prop-types'
4-
import Svg, { Defs, G, Rect, Path, Image, ClipPath } from 'react-native-svg'
5-
import genMatrix from './genMatrix'
1+
import React, {PureComponent} from 'react';
2+
import {Image as RNImage} from 'react-native';
3+
import PropTypes from 'prop-types';
4+
import Svg, {Defs, G, Rect, Path, Image, ClipPath} from 'react-native-svg';
5+
import genMatrix from './genMatrix';
66

7-
const DEFAULT_SIZE = 100
8-
const DEFAULT_BG_COLOR = 'white'
7+
const DEFAULT_SIZE = 100;
8+
const DEFAULT_BG_COLOR = 'white';
9+
10+
/* calculate the size of the cell and draw the path */
11+
function calculateMatrix(props) {
12+
const {value, size, ecl, onError} = props;
13+
try {
14+
const matrix = genMatrix(value, ecl);
15+
const cellSize = size / matrix.length;
16+
return {
17+
value,
18+
size,
19+
cellSize,
20+
path: transformMatrixIntoPath(cellSize, matrix)
21+
};
22+
} catch (error) {
23+
if (onError && typeof onError === 'function') {
24+
onError(error);
25+
} else {
26+
// Pass the error when no handler presented
27+
throw error;
28+
}
29+
}
30+
return {};
31+
}
32+
33+
/* project the matrix into path draw */
34+
function transformMatrixIntoPath(cellSize, matrix) {
35+
// adjust origin
36+
let d = '';
37+
matrix.forEach((row, i) => {
38+
let needDraw = false;
39+
row.forEach((column, j) => {
40+
if (column) {
41+
if (!needDraw) {
42+
d += `M${cellSize * j} ${cellSize / 2 + cellSize * i} `;
43+
needDraw = true;
44+
}
45+
if (needDraw && j === matrix.length - 1) {
46+
d += `L${cellSize * (j + 1)} ${cellSize / 2 + cellSize * i} `;
47+
}
48+
} else {
49+
if (needDraw) {
50+
d += `L${cellSize * j} ${cellSize / 2 + cellSize * i} `;
51+
needDraw = false;
52+
}
53+
}
54+
});
55+
});
56+
return d;
57+
}
958

1059
/**
1160
* A simple component for displaying QR Code using svg
@@ -41,6 +90,7 @@ export default class QRCode extends PureComponent {
4190
*/
4291
onError: PropTypes.func
4392
};
93+
4494
static defaultProps = {
4595
value: 'This is a QR Code.',
4696
size: DEFAULT_SIZE,
@@ -53,84 +103,52 @@ export default class QRCode extends PureComponent {
53103
ecl: 'M',
54104
onError: undefined
55105
};
56-
constructor (props) {
57-
super(props)
58-
this._matrix = null
59-
this._cellSize = null
60-
this._path = null
61-
this.setMatrix(props)
62-
}
63-
componentWillUpdate (nextProps) {
64-
// if value has changed, re-setMatrix
65-
if (nextProps.value !== this.props.value || nextProps.size !== this.props.size) {
66-
this.setMatrix(nextProps)
67-
}
106+
107+
constructor(props) {
108+
super(props);
109+
this.state = calculateMatrix(props);
68110
}
69-
/* calculate the size of the cell and draw the path */
70-
setMatrix (props) {
71-
const { value, size, ecl, onError } = props
72-
try {
73-
this._matrix = genMatrix(value, ecl)
74-
this._cellSize = size / this._matrix.length
75-
this._path = this.transformMatrixIntoPath()
76-
} catch (error) {
77-
if (onError && typeof onError === 'function') {
78-
onError(error)
79-
} else {
80-
// Pass the error when no handler presented
81-
throw error
82-
}
111+
112+
static getDerivedStateFromProps(props, state) {
113+
// if value has changed, re-calculateMatrix
114+
if (props.value !== state.value || props.size !== state.size) {
115+
return calculateMatrix(props);
83116
}
117+
return null;
84118
}
85-
/* project the matrix into path draw */
86-
transformMatrixIntoPath () {
87-
const matrix = this._matrix
88-
const cellSize = this._cellSize
89-
// adjust origin
90-
let d = ''
91-
matrix.forEach((row, i) => {
92-
let needDraw = false
93-
row.forEach((column, j) => {
94-
if (column) {
95-
if (!needDraw) {
96-
d += `M${cellSize * j} ${cellSize / 2 + cellSize * i} `
97-
needDraw = true
98-
}
99-
if (needDraw && j === matrix.length - 1) {
100-
d += `L${cellSize * (j + 1)} ${cellSize / 2 + cellSize * i} `
101-
}
102-
} else {
103-
if (needDraw) {
104-
d += `L${cellSize * j} ${cellSize / 2 + cellSize * i} `
105-
needDraw = false
106-
}
107-
}
108-
})
109-
})
110-
return d
111-
}
112-
render () {
119+
120+
render() {
113121
const {
114-
getRef, size, color, backgroundColor,
115-
logo, logoSize, logoMargin, logoBackgroundColor, logoBorderRadius
116-
} = this.props
122+
getRef,
123+
size,
124+
color,
125+
backgroundColor,
126+
logo,
127+
logoSize,
128+
logoMargin,
129+
logoBackgroundColor,
130+
logoBorderRadius
131+
} = this.props;
132+
133+
const logoPosition = size / 2 - logoSize / 2 - logoMargin;
134+
const logoWrapperSize = logoSize + logoMargin * 2;
135+
const logoWrapperBorderRadius =
136+
logoBorderRadius + (logoBorderRadius && logoMargin);
117137

118-
const logoPosition = size / 2 - logoSize / 2 - logoMargin
119-
const logoWrapperSize = logoSize + logoMargin * 2
120-
const logoWrapperBorderRadius = logoBorderRadius + (logoBorderRadius && logoMargin)
138+
const {cellSize, path} = this.state;
121139

122140
return (
123141
<Svg ref={getRef} width={size} height={size}>
124142
<Defs>
125-
<ClipPath id='clip-wrapper'>
143+
<ClipPath id="clip-wrapper">
126144
<Rect
127145
width={logoWrapperSize}
128146
height={logoWrapperSize}
129147
rx={logoWrapperBorderRadius}
130148
ry={logoWrapperBorderRadius}
131149
/>
132150
</ClipPath>
133-
<ClipPath id='clip-logo'>
151+
<ClipPath id="clip-logo">
134152
<Rect
135153
width={logoSize}
136154
height={logoSize}
@@ -139,38 +157,30 @@ export default class QRCode extends PureComponent {
139157
/>
140158
</ClipPath>
141159
</Defs>
142-
<Rect
143-
width={size}
144-
height={size}
145-
fill={backgroundColor}
146-
/>
147-
{ this._path && this._cellSize && (
148-
<Path
149-
d={this._path}
150-
stroke={color}
151-
strokeWidth={this._cellSize}
152-
/>
160+
<Rect width={size} height={size} fill={backgroundColor} />
161+
{path && cellSize && (
162+
<Path d={path} stroke={color} strokeWidth={cellSize} />
153163
)}
154164
{logo && (
155165
<G x={logoPosition} y={logoPosition}>
156166
<Rect
157167
width={logoWrapperSize}
158168
height={logoWrapperSize}
159169
fill={logoBackgroundColor}
160-
clipPath='url(#clip-wrapper)'
170+
clipPath="url(#clip-wrapper)"
161171
/>
162172
<G x={logoMargin} y={logoMargin}>
163173
<Image
164174
width={logoSize}
165175
height={logoSize}
166-
preserveAspectRatio='xMidYMid slice'
176+
preserveAspectRatio="xMidYMid slice"
167177
href={logo}
168-
clipPath='url(#clip-logo)'
178+
clipPath="url(#clip-logo)"
169179
/>
170180
</G>
171181
</G>
172182
)}
173183
</Svg>
174-
)
184+
);
175185
}
176186
}

0 commit comments

Comments
 (0)