Home > Enterprise >  How to save a component state after re-rendering? React js
How to save a component state after re-rendering? React js

Time:11-24

There are some movie cards that clients can click on them and their color changes to gray with a blur effect, meaning that the movie is selected. At the same time, the movie id is transferred to an array list. In the search bar, you can search for your favorite movie but the thing is after you type something in the input area the movie cards that were gray loses their style (I suppose because they are deleted and rendered again based on my code) but the array part works well and they are still in the array list. How can I preserve their style?

Search Page:

export default function Index(data) {
  const info = data.data.body.result;
  const [selectedList, setSelectedList] = useState([]);
  const [searchTerm, setSearchTerm] = useState('');

  return (
    <>
      <main className={parentstyle.main_container}>
        <NavBar />
        <div className={style.searchbar_container}>
          <CustomSearch
            onChange={(e) => {
              setSearchTerm(e.target.value);
            }}
          />
        </div>
        <div className={style.card_container}>
          {info
            .filter((value) => {
              if (searchTerm === '') {
                return value;
              } else if (
                value.name
                  .toLocaleLowerCase()
                  .includes(searchTerm.toLocaleLowerCase())
              ) {
                return value;
              }
            })
            .map((value, key) => {
              return (
                <MovieCard
                  movieName={value.name}
                  key={key}
                  movieId={value._id}
                  selected={selectedList}
                  setSelected={setSelectedList}
                  isSelected={false}
                />
              );
            })}
        </div>
        <div>
          <h3 className={style.test}>{selectedList}</h3>
        </div>
      </main>

Movie Cards Component:

export default function Index({ selected, movieName, movieId, setSelected }) {
  const [isActive, setActive] = useState(false);

  const toggleClass = () => {
    setActive(!isActive);
  };

  useEffect(()=>{

    
  })

  const pushToSelected = (e) => {
    if (selected.includes(e.target.id)) {
      selected.splice(selected.indexOf(e.target.id), 1);

      console.log(selected);
    } else {
      selected.push(e.target.id);

      console.log(selected);
      console.log(e.target);
    }
    setSelected([...selected]);
    toggleClass();
  };

  return (
    <div>
      <img
        className={isActive ? style.movie_selected : style.movie}
        id={movieId}
        name={movieName}
        src={`images/movies/${movieName}.jpg`}
        alt={movieName}
        onClick={pushToSelected}
      />
      <h3 className={style.title}>{movieName}</h3>
    </div>
  );
}

Here is when the input bar is empty

CodePudding user response:

I can't directly test your code so I will assume that this is the issue:

  1. Don't directly transform a state (splice/push) - always create a clone or something.
  2. Make the setActive based on the list and not dependent. (this is the real issue why the style gets removed)

try this:

  const pushToSelected = (e) => {
    if (selected.includes(e.target.id)) {
      
      // filter out the id
      setSelected(selected.filter(s => s !== e.target.id));
      return;
    }
    
    // add the id
    setSelected([...selected, e.target.id]);
  };

  // you may use useMemo here. up to you.
  const isActive = selected.includes(movieId);

  return (
    <div>
      <img
        className={isActive ? style.movie_selected : style.movie}
        id={movieId}
        name={movieName}
        src={`images/movies/${movieName}.jpg`}
        alt={movieName}
        onClick={pushToSelected}
      />
      <h3 className={style.title}>{movieName}</h3>
    </div>
  );

CodePudding user response:

This is a very broad topic. The best thing you can do is look up "React state management". As with everything in the react ecosystem it can be handled by various different libraries. But as of the latest versions of React, you can first start by checking out the built-in tools: Check out the state lifecycle: https://reactjs.org/docs/state-and-lifecycle.html (I see in your example you are using useState hooks, but I am adding these for more structured explanation for whoever needs it)

Then you might want to look at state-related hooks such as useState: https://reactjs.org/docs/hooks-state.html

useEffect (to go with useState): https://reactjs.org/docs/hooks-effect.html

And useContext: https://reactjs.org/docs/hooks-reference.html#usecontext

And for things outside of the built-in toolset, there are many popular state management libraries that also work with React with the most popular being: Redux, React-query, Mobx, Recoil, Flux, Hook-state. Please keep in mind that what you should use is dependant on your use case and needs. These can also help you out to persist your state not only between re-renders but also between refreshes of your app. More and more libraries pop up every day.

This is an ok article with a bit more info: https://dev.to/workshub/state-management-battle-in-react-2021-hooks-redux-and-recoil-2am0#:~:text=State management is simply a,you can read and write.&text=When a user performs an,occur in the component's state.

  • Related