ThakurBallary / react-native-radio-buttons-group

Simple, best and easy to use radio buttons for react native apps.
MIT License
263 stars 71 forks source link

Mutates original object #44

Closed amerikan closed 2 years ago

amerikan commented 2 years ago

Hi, I'm using this component for an app. I followed the docs, though ran into trouble where it will mutate the original object, and never reset it back when the parent component unmounts/remounts. When it gets re-mounted it contains same values as the last time it was modified, it does not revert back to the original object! :*(

For the example the code is shown in docs as follows (added notes as comments):

import React, { useState } from 'react';
import RadioGroup from 'react-native-radio-buttons-group';

const radioButtonsData = [{  // <-- ORIGINAL OBJECT
    id: '1', // acts as primary key, should be unique and non-empty string
    label: 'Option 1',
    value: 'option1'
}, {
    id: '2',
    label: 'Option 2',
    value: 'option2'
}]

export default function App() {

    const [radioButtons, setRadioButtons] = useState(radioButtonsData) // <--- PASSING ORIGINAL OBJECT

    function onPressRadioButton(radioButtonsArray) {
        setRadioButtons(radioButtonsArray);
    }

    return (
        <RadioGroup 
            radioButtons={radioButtons} 
            onPress={onPressRadioButton} 
        />
    );
}

I believe the problem is here (RadioGroup.tsx):

export default function RadioGroup({ containerStyle, layout = 'column', onPress, radioButtons }: RadioGroupProps) {

  const [radioButtonsLocal, setRadioButtonsLocal] = useState<RadioButtonProps[]>(radioButtons); // <-- this is OK

  if(!isEqual(radioButtons, radioButtonsLocal)) {
    setRadioButtonsLocal(radioButtons); 
  }

  function handlePress(id: string) {

     console.log("Same object ref?:", radioButtonsLocal === radioButtons); // <--- TRUE!

    for (const button of radioButtonsLocal) {
      if (button.selected && button.id === id) return;
      button.selected = button.id === id;   // <--- MUTATING ORIGINAL OBJECT radioButtonsData
    }
    setRadioButtonsLocal([...radioButtonsLocal]);
    if (onPress) {
      onPress(radioButtonsLocal);
    }
  }

Is this expected behavior? Currently, the workaround I am doing is to put the object inside the component so that it gets recreated each time fresh.

import React, { useState } from 'react';
import RadioGroup from 'react-native-radio-buttons-group';

export default function App() {

 const [radioButtons, setRadioButtons] = useState([  // <-- placed inside of component
    {
      id: "1", // acts as primary key, should be unique and non-empty string
      label: "Option 1",
      value: "option1",
    },
    {
      id: "2",
      label: "Option 2",
      value: "option2",
    },
  ]);

    function onPressRadioButton(radioButtonsArray) {
        setRadioButtons(radioButtonsArray);
    }

    return (
        <RadioGroup 
            radioButtons={radioButtons} 
            onPress={onPressRadioButton} 
        />
    );
}
ThakurBallary commented 2 years ago

@amerikan Thank you for contributing!! I have updated the docs