|
1 | 1 | // @flow
|
2 | 2 | import React from 'react';
|
3 | | -import CheckboxContext from './context'; |
| 3 | +import {Provider} from './context'; |
4 | 4 |
|
5 | 5 | type CheckboxGroupPropsT = {
|
6 | | - children: *, |
| 6 | + children: any, |
7 | 7 | name?: string,
|
8 | | - onChange: (values: string[], e: SyntheticEvent<HTMLInputElement>) => *, |
9 | | - // Disable react/no-unused-prop-types until this bug is fixed and merged: |
10 | | - // https://github.com/yannickcr/eslint-plugin-react/issues/1751 |
11 | | - // eslint-disable-next-line react/no-unused-prop-types |
| 8 | + onChange: (e: SyntheticInputEvent<HTMLInputElement>, values: string[]) => any, |
12 | 9 | values?: string[],
|
13 | 10 | };
|
14 | 11 |
|
15 | 12 | type CheckboxGroupStateT = {
|
16 | | - name?: string, |
17 | | - onChange?: (e: SyntheticEvent<HTMLInputElement>, values: Array<string>) => void, |
18 | 13 | values: string[],
|
19 | 14 | };
|
20 | 15 |
|
21 | 16 | export default class CheckboxGroup extends React.Component<
|
22 | 17 | CheckboxGroupPropsT,
|
23 | 18 | CheckboxGroupStateT
|
24 | 19 | > {
|
25 | | - static getDerivedStateFromProps(nextProps: CheckboxGroupPropsT) { |
26 | | - if (!nextProps.values) { |
27 | | - return { |
28 | | - values: [], |
29 | | - name: nextProps.name, |
30 | | - }; |
31 | | - } |
| 20 | + state = { |
| 21 | + values: Array.isArray(this.props.values) ? this.props.values : [], |
| 22 | + }; |
32 | 23 |
|
33 | | - if (Array.isArray(nextProps.values)) { |
34 | | - return { |
35 | | - values: nextProps.values.map((value) => value.toString()), |
36 | | - name: nextProps.name, |
37 | | - }; |
38 | | - } |
| 24 | + onChange = (e: SyntheticInputEvent<HTMLInputElement>) => { |
| 25 | + e.persist(); |
| 26 | + const { |
| 27 | + currentTarget: { value, checked }, |
| 28 | + } = e; |
39 | 29 |
|
40 | | - if (typeof nextProps.values === 'string') { |
41 | | - return { |
42 | | - values: [nextProps.values], |
43 | | - name: nextProps.name, |
44 | | - }; |
| 30 | + if (checked) { |
| 31 | + this.addValue(e, value); |
| 32 | + } else { |
| 33 | + this.removeValue(e, value); |
45 | 34 | }
|
46 | | - } |
47 | | - |
48 | | - constructor(props: CheckboxGroupPropsT, state: CheckboxGroupStateT) { |
49 | | - super(props, state); |
50 | | - this.state = { |
51 | | - ...this.state, |
52 | | - onChange: this.onChange, |
53 | | - }; |
54 | | - } |
55 | | - |
56 | | - state = { |
57 | | - values: [], |
58 | | - name: this.props.name, |
59 | 35 | };
|
60 | 36 |
|
61 | | - shouldComponentUpdate(nextProps: CheckboxGroupPropsT, nextState: CheckboxGroupStateT) { |
62 | | - if (this.props !== nextProps || this.state !== nextState) { |
63 | | - return true; |
| 37 | + customOnChangeHandler = ( |
| 38 | + originalEvent: SyntheticInputEvent<HTMLInputElement>, |
| 39 | + values: string[] |
| 40 | + ) => { |
| 41 | + if (typeof this.props.onChange === 'function') { |
| 42 | + this.props.onChange(originalEvent, values); |
64 | 43 | }
|
65 | | - return false; |
66 | | - } |
| 44 | + }; |
67 | 45 |
|
68 | | - removeValue = (value: string,originalEvent: SyntheticEvent<HTMLInputElement>) => { |
| 46 | + removeValue = (originalEvent: SyntheticInputEvent<HTMLInputElement>,value: string) => { |
69 | 47 | this.setState(
|
70 | | - (state) => { |
71 | | - const { values } = state; |
72 | | - const index = values.indexOf(value); |
73 | | - if (index !== -1) { |
74 | | - const nextValues = values.slice(); |
75 | | - nextValues.splice(index, 1); |
76 | | - return { |
77 | | - values: nextValues, |
78 | | - }; |
79 | | - } |
80 | | - }, |
| 48 | + ({ values }) => ({ |
| 49 | + values: values.includes(value) |
| 50 | + ? values.slice().filter((item) => item !== value) |
| 51 | + : values, |
| 52 | + }), |
81 | 53 | () => {
|
82 | | - if (typeof this.props.onChange === 'function') { |
83 | | - this.props.onChange(this.state.values, originalEvent); |
84 | | - } |
| 54 | + this.customOnChangeHandler(originalEvent, this.state.values); |
85 | 55 | }
|
86 | 56 | );
|
87 | 57 | };
|
88 | 58 |
|
89 | | - addValue = (value: string,originalEvent: SyntheticEvent<HTMLInputElement>) => { |
| 59 | + addValue = (originalEvent: SyntheticInputEvent<HTMLInputElement>,value: string) => { |
90 | 60 | this.setState(
|
91 | | - (state) => { |
92 | | - const { values } = state; |
93 | | - if (values.indexOf(value) === -1) { |
94 | | - return { |
95 | | - values: values.concat(value), |
96 | | - }; |
97 | | - } |
98 | | - }, |
| 61 | + ({ values }) => ({ |
| 62 | + values: values.indexOf(value) === -1 ? values.slice().concat(value) : values, |
| 63 | + }), |
99 | 64 | () => {
|
100 | | - if (typeof this.props.onChange === 'function') { |
101 | | - this.props.onChange(this.state.values, originalEvent); |
102 | | - } |
| 65 | + this.customOnChangeHandler(originalEvent, this.state.values); |
103 | 66 | }
|
104 | 67 | );
|
105 | 68 | };
|
106 | 69 |
|
107 | | - onChange = (e: SyntheticEvent<HTMLInputElement>) => { |
108 | | - e.persist(); |
109 | | - const { currentTarget: { value, checked } } = e; |
110 | | - if (checked) { |
111 | | - this.addValue(value, e); |
112 | | - } else { |
113 | | - this.removeValue(value, e); |
114 | | - } |
115 | | - }; |
116 | | - |
117 | 70 | render() {
|
118 | | - return ( |
119 | | - <CheckboxContext.Provider value={this.state}> |
120 | | - {this.props.children} |
121 | | - </CheckboxContext.Provider> |
122 | | - ); |
| 71 | + const { children, name } = this.props; |
| 72 | + |
| 73 | + const contextValue = { |
| 74 | + onChange: this.onChange, |
| 75 | + values: this.state.values, |
| 76 | + name, |
| 77 | + }; |
| 78 | + |
| 79 | + return <Provider value={contextValue}>{children}</Provider>; |
123 | 80 | }
|
124 | 81 | }
|
0 commit comments