n4kz / react-native-material-dropdown

Material dropdown with consistent behaviour on iOS and Android
Other
732 stars 597 forks source link

Drop-down is too slow in my case . It takes too long . #88

Open moussasarr opened 6 years ago

moussasarr commented 6 years ago

My drop-down is pretty slow. It especially takes a long time if I try to change my major. Or anything dealing with adding or editing a major . I really need to make adding or editing a major much faster. I am not sure the reason why editing or adding a major is taking too long with react-native-material-dropdown. And I am not sure about how to go at making adding and editing a major much faster. So I am posting the entire component and I am commenting parts that deal with adding or editing a major. I Here is the entire component code:

import React from 'react';
import PropTypes from 'prop-types';
import { View, ScrollView, Text, TouchableOpacity } from 'react-native';
import { connect } from 'react-redux';
import { compose, withStateHandlers } from 'recompose';
import { Dropdown } from 'react-native-material-dropdown';
import { Icon } from 'react-native-material-ui';
import R from 'ramda';
import { ConnectivityRenderer } from 'react-native-offline';
import NetworkConnectivity from '../error/NetworkConnectivity';
import { toArray } from '../selectors';
import { Container, Switch, SwitchOption } from './common';
import { editStudent } from '../actions';

const propTypes = {
  toolbar: PropTypes.elem,
  loading: PropTypes.bool,
  university: PropTypes.shape({
  id: PropTypes.string,
  name: PropTypes.string,
  }),
  universities: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.string,
      name: PropTypes.string,
    })
  ),
  degrees: PropTypes.arrayOf(
    PropTypes.shape({
      id: PropTypes.string,
      name: PropTypes.string,
    })
  ),
  studentDegrees: PropTypes.arrayOf(
    PropTypes.shape({
      index: PropTypes.number,
      track: PropTypes.string,
    })
  ),
  errors: PropTypes.shape({
    university: PropTypes.string,
    degree: PropTypes.string,
  }),
  year: PropTypes.string,
  onUniversityChange: PropTypes.func,
  onTermChange: PropTypes.func,
  onDegreeChange: PropTypes.func,
  onYearChange: PropTypes.func,
  onTrackChange: PropTypes.func,
  onAddDegree: PropTypes.func,
  onDone: PropTypes.func,
};

const contextTypes = {
  uiTheme: PropTypes.object.isRequired,
};

const validate = state => {
  const result = {};

  if (!state.university.id) {
    result.university = 'You should select an university';
  }

  return result;
};

const enhance = compose(
  connect(
    ({ user, universities, degrees }) => ({
      studentId: user.id,
      user,
      universities: toArray(universities),
      degrees: toArray(degrees),
    }),
    { editStudent }
  ),
  withStateHandlers(
    props => {
      return {
        university: props.user.university || {},
        year: props.user.academicClass || 'freshman',
        studentDegrees: R.isEmpty(props.degrees)
          ? []
          : R.isEmpty(props.user.studentDegrees)
            ? [{ degree_id: props.degrees[0].id, track: 'Major' }]
            : R.values(props.user.studentDegrees),
        errors: {},
       };
    },
    {
      onUniversityChange: () => (value, index, data) => ({
        university: data[index],
       }),
      onYearChange: () => year => ({ year }),
      onTrackChange: state => ({ idx, track }) => ({
        studentDegrees: R.update(
          idx,
          R.assoc('track', track, state.studentDegrees[idx]),
          state.studentDegrees
        ),
      }),

      // Fucntion dealing with degree change

      onDegreeChange: (state, props) => ({ idx, index }) => ({
         studentDegrees: R.update(
          idx,
          R.assoc(
            'degree_id',
            props.degrees[index].id,
            state.studentDegrees[idx]
          ),
          state.studentDegrees
        ),
      }),

    // Function dealing with degree adding

    onAddDegree: (state, props) => () => ({
        studentDegrees: R.append(
          {
            degree_id: props.degrees[0].id,
            track: 'Major',
          },
          state.studentDegrees
        ),
      }),
      onRemoveDegree: state => idx => ({
        studentDegrees: [
          ...state.studentDegrees.slice(0, idx),
          ...state.studentDegrees.slice(idx + 1),
        ],
      }),

      // When the user is done with settings.
      // This function communicates with the back end to save things in the remote database
      onDone: (state, { studentId, editStudent }) => () => {
      const errors = validate(state);
        if (Object.keys(errors).length !== 0) {
          return { errors };
        }

        editStudent(
          studentId,
          state.year,
          state.university.id,
          state.studentDegrees
        );
      },
    }
  )
);

// The Settings Component 
  const FormUserSettings = (props, context) => {
  const styles = getStyles(props, context);

  return (
    <ConnectivityRenderer>
      {isConnected => (
        isConnected ? (
          <Container>
            {React.cloneElement(props.toolbar, {
              onRightElementPress: props.onDone,
            })}
            <ScrollView style={styles.container}>
              <Text
                style={[
                  styles.title,
                  props.errors.university ? styles.titleError : {},
                ]}
              >
                University
              </Text>

          // Selecting a university
              <Dropdown
                label="Select university..."
                data={props.universities.map(u => ({ id: u.id, value: u.name }))}
                onChangeText={props.onUniversityChange}
                value={props.university.name}
              />
              {props.errors.university &&
                <Text style={styles.errorMessage}>
                  {props.errors.university}
                </Text>}
              <View style={{ height: 16 }} />
                <Text style={styles.title}>Current Year</Text>
               <View style={{ height: 8 }} />
              <Switch
                value={props.year}
                onChange={props.onYearChange}
                selectedColor={styles.switchSelectedColor}
                unselectedColor={styles.switchUnselectedColor}
               >
                <SwitchOption text="Freshman" value="freshman" />
                <SwitchOption text="Sophomore" value="sophomore" />
                <SwitchOption text="Junior" value="junior" />
                <SwitchOption text="Senior" value="senior" />
                </Switch>
               <View style={{ height: 16 }} />
               <Text
                style={[styles.title, props.errors.degree ? styles.titleError : {}]}
              >
            Major / Minors
          </Text>
          {!R.isEmpty(props.degrees) &&
            props.studentDegrees.map((sd, idx) => {
              const degree = R.find(R.propEq('id', sd.degree_id), props.degrees);

              return (
                <View
                  key={`sd-${idx}`}
                  style={{ flex: 1, height: 96, marginTop: 24 }}
                >
                  <View
                    style={{
                      flex: 1,
                      flexDirection: 'row',
                      alignItems: 'flex-end',
                    }}
                  >
                    <View style={{ flex: 1 }}>
                      <Dropdown
                        style={{ flex: 1 }}
                        label="Select degree..."
                        data={props.degrees.map(d => ({
                          id: d.id,
                          value: d.name,
                        }))}
                        onChangeText={(value, index) =>
                          props.onDegreeChange({ idx, index })}
                        value={degree ? degree.name : ''}
                      />
                    </View>
                    {props.studentDegrees.length !== 1 &&
                      <TouchableOpacity
                        style={{ marginBottom: 8, paddingLeft: 24 }}
                        onPress={() => props.onRemoveDegree(idx)}
                      >
                        <Icon name="delete" size={24} />
                      </TouchableOpacity>}
                  </View>
                  <Switch
                    value={sd.track}
                    onChange={track => props.onTrackChange({ idx, track })}
                    selectedColor={styles.switchSelectedColor}
                    unselectedColor={styles.switchUnselectedColor}
                  >
                    <SwitchOption text="Major" value="Major" />
                    <SwitchOption text="Minor" value="Minor" />
                    <SwitchOption text="Certificate" value="Cert" />
                  </Switch>
                </View>
              );
            })}
          <TouchableOpacity style={{ padding: 10 }} onPress={props.onAddDegree}>
            <Text style={styles.addDegreeText}>+ Degree</Text>
          </TouchableOpacity>
        </ScrollView>
      </Container>
    ) : (
      <Container>
        {React.cloneElement(props.toolbar, {
          onRightElementPress: props.onDone,
        })}
        <NetworkConnectivity />
        <ScrollView style={styles.container}>
          <Text
            style={[
              styles.titleDisabled,
              props.errors.university ? styles.titleError : {},
            ]}
          >
            University
          </Text>
          <Dropdown
            label=""
            data={props.universities.map(u => ({ id: u.id, value: u.name }))}
            onChangeText={props.onUniversityChange}
            value={props.university.name}
            disabled={true}
            editable={false}
          />
          {props.errors.university &&
            <Text style={styles.errorMessage}>
              {props.errors.university}
            </Text>}
          <View style={{ height: 16 }} />
          <Text style={styles.titleDisabled}>Current Year</Text>
          <View style={{ height: 8 }} />
          <Switch
            value={props.year}
            onChange={props.onYearChange}
            selectedColor={styles.disabledSwitchSelectedColor}
            unselectedColor={styles.switchUnselectedColor}
          >
            <SwitchOption text="Freshman" value="freshman" />
            <SwitchOption text="Sophomore" value="sophomore" />
            <SwitchOption text="Junior" value="junior" />
            <SwitchOption text="Senior" value="senior" />
          </Switch>
          <View style={{ height: 16 }} />
          <Text
            style={[styles.titleDisabled, props.errors.degree ? styles.titleError : {}]}
          >
            Major / Minors
          </Text>

          // The problem of slowness starts here
          // I feel like something here should be improved
          {!R.isEmpty(props.degrees) &&
            props.studentDegrees.map((sd, idx) => {
              const degree = R.find(R.propEq('id', sd.degree_id), props.degrees);

                  return (
                    <View
                      key={`sd-${idx}`}
                      style={{ flex: 1, height: 96, marginTop: 24 }}
                    >
                      <View
                        style={{
                          flex: 1,
                          flexDirection: 'row',
                          alignItems: 'flex-end',
                        }}
                      >
                        <View style={{ flex: 1 }}>
                          <Dropdown
                            style={{ flex: 1 }}
                            label="Select degree..."
                            data={props.degrees.map(d => ({
                              id: d.id,
                              value: d.name,
                            }))}
                            disabled={true}
                            editable={false}
                            onChangeText={(value, index) =>
                              props.onDegreeChange({ idx, index })}
                            value={degree ? degree.name : ''}
                          />
                        </View>
                      </View>
                      <Switch
                        value={sd.track}
                         onChange={track => props.onTrackChange({ idx, track })}
                        selectedColor={styles.disabledSwitchSelectedColor}
                        unselectedColor={styles.switchUnselectedColor}
                      >
                        <SwitchOption text="Major" value="Major" />
                        <SwitchOption text="Minor" value="Minor" />
                        <SwitchOption text="Certificate" value="Cert" />
                      </Switch>
                    </View>
                  );
                })}
              <TouchableOpacity disabled={true} style={{ padding: 10 }} onPress={props.onAddDegree} disabled={true}>
                <Text style={styles.addDegreeTextDisabled}>+ Degree</Text>
              </TouchableOpacity>
            </ScrollView>
          </Container>
        )
      )}
    </ConnectivityRenderer>
  );
};

FormUserSettings.contextTypes = contextTypes;
FormUserSettings.propTypes = propTypes;

export default enhance(FormUserSettings);
chauhanshubham-dev commented 6 years ago

+1

mingca commented 6 years ago

+1

Thanmai-C commented 6 years ago

+1

kmistry98 commented 6 years ago

+1

sathishmscict commented 6 years ago

+1

danisbubblesdad commented 6 years ago

Does using the animationDuration property at a lower number of milliseconds not help? The default is 255.

moussasarr commented 6 years ago

No I solved it. react-native-matrerial-dropdown was using a ScrollView in versions before 8.0.0. So it was extremely slow for large lists like in my case. I just had to upgrade to the lastest version, where they use a FlatList instead, which is much faster.

NdaJunior commented 6 years ago

I've upgraded to version 0.11.1 and the dropdown is still super slow...anyone else experiencing this?

Ryeru commented 6 years ago

@NdaJunior It is extremely slow in 0.11.1, I have the same problem

wzup commented 6 years ago

SLOOOOOWWW

themakerman commented 6 years ago

SLOWWWWWW........i thought its my code but its the module....

harshitjee commented 6 years ago

here tooo......very slow

harshitjee commented 6 years ago

guys i hv improved the slowness issue please check https://github.com/harshitjee/react-native-material-dropdown.git use npm install https://github.com/harshitjee/react-native-material-dropdown.git and give me yr feedback

sachinar94 commented 5 years ago

set there animationDuration to get fast response. slow because of animation at there start.

animationDuration={300}