React Native slider re-renders to 0

Viewed 211

I am creating a project where by clicking a button on my main page, a modal opens and it has some sliders and switches. You can change the value of these sliders and switches and close the modal. but when you open the modal back up it should show the changed values. When I close my modal and open it again all my sliders and switches get rendered with value 0.

Structure of my code

The code for the switches and sliders (In component called "TaskListEdit"):

const Chooser = (task) => {
    switch (task.inputType) {
      case "slider":
        return (
          <Slider
            style={{ width: 200, height: 40 }}
            minimumValue={0}
            maximumValue={100}
            minimumTrackTintColor="#ff9900"
            maximumTrackTintColor="#9494b8"
            value={task.value}
            onSlidingComplete={(sliderValue) =>
              addModifiedTasks(task, sliderValue)
            }
          />
        );

      case "switch":
        return (
          <Switch
            trackColor={{ false: "#767577", true: "#81b0ff" }}
            thumbColor={isEnabled ? "#f5dd4b" : "#f4f3f4"}
            ios_backgroundColor="#3e3e3e"
            onValueChange={(switchValue) => {
              addModifiedTasks(task, switchValue);
            }}
            value={isEnabled}
          />
        );
    }
  };

And the code for the modal (In a different component):

     <Modal
          animationType="fade"
          transparent={true}
          visible={modalVisible}
          supportedOrientations={["portrait", "landscape"]}
        >
          <Pressable
            onPress={() => setModalVisible(!modalVisible)}
            style={{
              flex: 1,
              alignItems: "center",
              justifyContent: "center",
              backgroundColor: "rgba(0,0,0,0.5)",
            }}
          >
            <View style={styles.centeredView}>
              <View style={styles.modalView}>
                <TaskListEdit
                  tasks={tasks}
                  statefunction={setCellTasks}
                  cellTasks={cellTasks}
                  setModalVisible={setModalVisible}
                />
                <Button
                  title="Back"
                  style={styles.buttonClose}
                  onPress={() => setModalVisible(!modalVisible)}
                />
              </View>
            </View>
          </Pressable>
        </Modal>

To test the sliders, I included console.log inside the chooser function to output task.value and the value in fact is correct. For example, If I change the slider to 45, it returns 45, however, the slider shows 0. This is what makes it really confusing because I don't understand, how can slider's value output the correct number yet the display stay on 0.

2 Answers

I think you're having a problem with the state change part, so my suggestion to you would be to convert the "Chooser" function into a component. To eliminate incorrect display of values, useEffect will detect props changes and update the state in the component. For example:

const Chooser = memo(({task}) => {
   const [state, setState] = useState(task);
   
   useEffect(() => {
      setState(task);
   }, [task])
   
   const ItemRender = () => {
     switch (state.inputType) {
      case "slider":
        return (
          <Slider
            style={{ width: 200, height: 40 }}
            minimumValue={0}
            maximumValue={100}
            minimumTrackTintColor="#ff9900"
            maximumTrackTintColor="#9494b8"
            value={state.value}
            onSlidingComplete={(sliderValue) =>
              addModifiedTasks(state, sliderValue)
            }
          />
        );

      case "switch":
        return (
          <Switch
            trackColor={{ false: "#767577", true: "#81b0ff" }}
            thumbColor={isEnabled ? "#f5dd4b" : "#f4f3f4"}
            ios_backgroundColor="#3e3e3e"
            onValueChange={(switchValue) => {
              addModifiedTasks(state, switchValue);
            }}
            value={isEnabled}
          />
        );

      default:
        return (<View />)
    }
   }

  return ItemRender()
});

export default Chooser;

Then pass task as props from where you use this component.

<Chooser task={yourTaskData} />

You should add onValueChange to your slider component.

onValueChange={(val) => setTaskValue(val)}

I haven't tried your code but this should nudge you down the right path.

Related