11/* eslint-disable react-hooks/exhaustive-deps */
2- import React , { useEffect , useReducer } from 'react' ;
2+ import React from 'react' ;
33
44import PropTypes from 'prop-types' ;
55import clsx from 'clsx' ;
6- import isEqual from 'lodash/isEqual' ;
7- import fnToString from '../utils/fn-to-string' ;
8- import reducer , { init } from './reducer' ;
9- import useIsMounted from '../hooks/use-is-mounted' ;
10-
11- const getSelectValue = ( stateValue , simpleValue , isMulti , allOptions ) => {
12- let enhancedValue = stateValue ;
13-
14- let hasSelectAll = isMulti && allOptions . find ( ( { selectAll } ) => selectAll ) ;
15- let hasSelectNone = isMulti && allOptions . find ( ( { selectNone } ) => selectNone ) ;
16-
17- if ( hasSelectAll || hasSelectNone ) {
18- enhancedValue = enhancedValue || [ ] ;
19- const optionsLength = allOptions . filter (
20- ( { selectAll, selectNone, divider, options } ) => ! selectAll && ! selectNone && ! divider && ! options
21- ) . length ;
22-
23- const selectedAll = optionsLength === enhancedValue . length ;
24- const selectedNone = enhancedValue . length === 0 ;
25-
26- enhancedValue = [
27- ...enhancedValue ,
28- ...( hasSelectAll && selectedAll ? [ simpleValue ? hasSelectAll . value : hasSelectAll ] : [ ] ) ,
29- ...( hasSelectNone && selectedNone ? [ simpleValue ? hasSelectNone . value : hasSelectNone ] : [ ] ) ,
30- ] ;
31- }
32-
33- return simpleValue ? allOptions . filter ( ( { value } ) => ( isMulti ? enhancedValue . includes ( value ) : isEqual ( value , enhancedValue ) ) ) : enhancedValue ;
34- } ;
35-
36- const handleSelectChange = ( option , simpleValue , isMulti , onChange , allOptions , removeSelectAll , removeSelectNone ) => {
37- let enhanceOption = option ;
38-
39- if ( removeSelectNone ) {
40- enhanceOption = enhanceOption . filter ( ( { selectNone } ) => ! selectNone ) ;
41- } else if ( removeSelectAll ) {
42- enhanceOption = enhanceOption . filter ( ( { selectAll } ) => ! selectAll ) ;
43- }
44-
45- const sanitizedOption = ! enhanceOption && isMulti ? [ ] : enhanceOption ;
46-
47- if ( isMulti && sanitizedOption . find ( ( { selectAll } ) => selectAll ) ) {
48- return onChange ( allOptions . filter ( ( { selectAll, selectNone, value } ) => ! selectAll && ! selectNone && value ) . map ( ( { value } ) => value ) ) ;
49- }
50-
51- if ( isMulti && sanitizedOption . find ( ( { selectNone } ) => selectNone ) ) {
52- return onChange ( [ ] ) ;
53- }
54-
55- return simpleValue
56- ? onChange ( isMulti ? sanitizedOption . map ( ( item ) => item . value ) : sanitizedOption ? sanitizedOption . value : undefined )
57- : onChange ( sanitizedOption ) ;
58- } ;
6+ import useSelect from '../use-select/use-select' ;
597
608const Select = ( {
619 invalid,
@@ -78,57 +26,25 @@ const Select = ({
7826 optionsTransformer,
7927 ...props
8028} ) => {
81- const [ state , originalDispatch ] = useReducer ( reducer , { optionsTransformer, propsOptions } , init ) ;
82- const dispatch = ( action ) => originalDispatch ( { ...action , optionsTransformer } ) ;
83-
84- const isMounted = useIsMounted ( ) ;
85-
86- const updateOptions = ( ) => {
87- dispatch ( { type : 'startLoading' } ) ;
88-
89- return loadOptions ( ) . then ( ( data ) => {
90- if ( isMounted . current ) {
91- if ( ! noValueUpdates ) {
92- if ( value && Array . isArray ( value ) ) {
93- const selectValue = value . filter ( ( value ) =>
94- typeof value === 'object' ? data . find ( ( option ) => value . value === option . value ) : data . find ( ( option ) => value === option . value )
95- ) ;
96- onChange ( selectValue . length === 0 ? undefined : selectValue ) ;
97- } else if ( value && ! data . find ( ( { value : internalValue } ) => internalValue === value ) ) {
98- onChange ( undefined ) ;
99- }
100- }
101-
102- dispatch ( { type : 'updateOptions' , payload : data } ) ;
103- }
104- } ) ;
105- } ;
106-
107- useEffect ( ( ) => {
108- if ( loadOptions ) {
109- updateOptions ( ) ;
110- }
111-
112- dispatch ( { type : 'initialLoaded' } ) ;
113- } , [ ] ) ;
114-
115- const loadOptionsStr = loadOptions ? fnToString ( loadOptions ) : '' ;
116-
117- useEffect ( ( ) => {
118- if ( loadOptionsStr && state . isInitialLoaded ) {
119- updateOptions ( ) ;
120- }
121- } , [ loadOptionsStr , loadOptionsChangeCounter ] ) ;
122-
123- useEffect ( ( ) => {
124- if ( state . isInitialLoaded ) {
125- if ( ! noValueUpdates && value && ! propsOptions . map ( ( { value } ) => value ) . includes ( value ) ) {
126- onChange ( undefined ) ;
127- }
128-
129- dispatch ( { type : 'setOptions' , payload : propsOptions } ) ;
130- }
131- } , [ propsOptions ] ) ;
29+ const {
30+ state,
31+ value : selectValue ,
32+ onChange : selectOnChange ,
33+ onInputChange,
34+ isFetching,
35+ } = useSelect ( {
36+ loadOptions,
37+ optionsTransformer,
38+ options : propsOptions ,
39+ noValueUpdates,
40+ onChange,
41+ value,
42+ loadOptionsChangeCounter,
43+ isSearchable : props . isSearchable ,
44+ pluckSingleValue,
45+ isMulti,
46+ simpleValue,
47+ } ) ;
13248
13349 const renderNoOptionsMessage = ( ) => ( Object . values ( state . promises ) . some ( ( value ) => value ) ? ( ) => updatingMessage : ( ) => noOptionsMessage ) ;
13450
@@ -149,34 +65,6 @@ const Select = ({
14965 ) ;
15066 }
15167
152- const onInputChange = ( inputValue ) => {
153- if ( inputValue && loadOptions && state . promises [ inputValue ] === undefined && props . isSearchable ) {
154- dispatch ( { type : 'setPromises' , payload : { [ inputValue ] : true } } ) ;
155-
156- loadOptions ( inputValue )
157- . then ( ( options ) => {
158- if ( isMounted . current ) {
159- dispatch ( {
160- type : 'setPromises' ,
161- payload : { [ inputValue ] : false } ,
162- options,
163- } ) ;
164- }
165- } )
166- . catch ( ( error ) => {
167- dispatch ( { type : 'setPromises' , payload : { [ inputValue ] : false } } ) ;
168- // eslint-disable-next-line no-console
169- console . error ( error ) ;
170- } ) ;
171- }
172- } ;
173-
174- const selectValue = pluckSingleValue ? ( isMulti ? value : Array . isArray ( value ) && value [ 0 ] ? value [ 0 ] : value ) : value ;
175-
176- const filteredLength = state . options . filter ( ( { selectAll, selectNone } ) => ! selectAll && ! selectNone ) . length ;
177- const shouldRemoveSelectAll = isMulti && state . options . find ( ( { selectAll } ) => selectAll ) && selectValue . length === filteredLength ;
178- const shouldRemoveSelectNone = isMulti && state . options . find ( ( { selectNone } ) => selectNone ) && selectValue . length === 0 ;
179-
18068 return (
18169 < SelectComponent
18270 className = { clsx ( classNamePrefix , {
@@ -187,10 +75,10 @@ const Select = ({
18775 options = { state . options }
18876 classNamePrefix = { classNamePrefix }
18977 isMulti = { isMulti }
190- value = { getSelectValue ( selectValue , simpleValue , isMulti , state . options ) }
191- onChange = { ( option ) => handleSelectChange ( option , simpleValue , isMulti , onChange , state . options , shouldRemoveSelectAll , shouldRemoveSelectNone ) }
78+ value = { selectValue }
79+ onChange = { selectOnChange }
19280 onInputChange = { onInputChange }
193- isFetching = { Object . values ( state . promises ) . some ( ( value ) => value ) }
81+ isFetching = { isFetching }
19482 noOptionsMessage = { renderNoOptionsMessage ( ) }
19583 hideSelectedOptions = { false }
19684 closeMenuOnSelect = { ! isMulti }
0 commit comments