ionic-team / ionic-framework

A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript.
https://ionicframework.com
MIT License
51.1k stars 13.5k forks source link

bug: IonReorderGroup event.detail.complete(array) alters other arrays in the dom #26920

Closed quarkstars closed 1 year ago

quarkstars commented 1 year ago

Prerequisites

Ionic Framework Version

Current Behavior

My use case is that I have a static list of podcast episodes. When the user clicks on an episode, it will load the entire list of episodes into state which the user could manipulate the order (sort of like a user's playlist).

However, calling event.detail.complete(episodes) reorders not just the user's list of episodes in state, but the original static list of episodes. Note the static list only shares the similarity of the episodes, but it does not use any of the same components (and does not have reorder components)

Expected Behavior

event.detail.complete(array) should only manipulate the dom for that list, not other lists on the dom.

Steps to Reproduce

If you create a similar set up, I'd expect you would get the same bug

//Static list that should not be altered by the reorder
          <SlideList isCarousel spaceBetween={5} setItemWidth={setEpisodeWidth} idealWidth={225}>
            {sampleEpisodes.map((episode, index) => {
              return (
                <SwiperSlide key={"latesteps-"+episode.objectId}>
                  <EpisodeCard 
                    size={episodeWidth}
                    list={{episodes: sampleEpisodes}}
                    index={index}
                    {...episode}
                  />
              </SwiperSlide>
              )
            })
            }
          </SlideList>
//On click, it will add the list to state

    const handleEpisodeClick = (e) => {
        player.setList(props.list);
    }
// This is the reorderable list. Notice the props.list, which is the state set in the previous code block
        <IonReorderGroup disabled={false} onIonItemReorder={handleReorder}>
        {props.list?.episodes.map((episode, _index) => {
          let weight = (_index === props.index) ? "font-bold" : "font-normal"
          return(
            <IonItem key={"list-"+episode.objectId}>
              <IonReorder slot="start"></IonReorder>
              <span className={`${weight}`}>{`Episode ${episode.number}`}</span>
            </IonItem>
          )
        })
        }
        </IonReorderGroup>
  function handleReorder(event: CustomEvent<ItemReorderEventDetail>) {

    let newEpisodeOrder = event.detail.complete(props.list.episodes);

    //I can comment out the below line, but it will still reorder the static list
    // props.setList(prev => {return {...prev, episdoes: newEpisodeOrder}});
  }

Code Reproduction URL

No response

Ionic Info

I forked this next repo https://github.com/mlynch/nextjs-tailwind-ionic-capacitor-starter/

So I am not sure how to get the ionic info since it's a next project and the ionic CLI isn't working on it

Additional Information

Here is a video showing the issue occuring on my app https://sharing.clickup.com/clip/p/t36124572/8f936723-ae24-4991-bc48-f2e672460516/screen-recording-2023-03-06-11%3A05.webm

liamdebeasi commented 1 year ago

Thanks for the report. Can you reproduce this issue in an Ionic starter app and provide a link to the repo? It's hard to say what is going on from the code snippets provided.

quarkstars commented 1 year ago

Ok hopefully I'll have time in a few days.

quarkstars commented 1 year ago

LOL Here's a temporary work around.

It seems the only way I can protect my original order on a similar array that is not suppose to be reordered is to stringify it and store it in state. Then whenever a reorder happens, I parse the string and reset the state of the array that isn't suppose to be changed. If I don't stringify it, the reorder changes the state too!

Hide yo state, hide yo dom, cause they reordering everybody out here.

  useEffect(() => {
    //Reset the list that wasn't suppose to be reordered
    setLatestEpisodes(JSON.parse(latestEpisodesString.current));
  }, [player.list])
  const [latestEpisodes, setLatestEpisodes] = useState(sampleEpisodes);
  const latestEpisodesString = useRef(JSON.stringify(sampleEpisodes));

This is FAR from ideal, so I'm I'll still find a the time to reproduce it later if that's what's needed to address this.

ionitron-bot[bot] commented 1 year ago

Thanks for the issue! This issue is being closed due to the lack of a reply. If this is still an issue with the latest version of Ionic, please create a new issue and ensure the template is fully filled out.

Thank you for using Ionic!