Search code examples
javascriptreactjsuse-state

Show and hide component based on current object


I have a parent component Editor with an array of objects mapping to another component Scene using map method:

function Editor() {
  const [URL, setURL] = useState();
  const [scenes, setScenes] = useState([]); 
const addScene = () => {
    const scene = {
      Id: Math.floor(Math.random() * 10000),
      JsonObj: canvas.getJsonObj(),
    };
    const cpScenes = [...scenes];
    cpScenes.push(scene);
    setScenes(cpScenes);
  };
  const removeScene = (scene) => {
    const cpScenes = scenes.filter((sc) => sc !== scene);
    setScenes(cpScenes);
  };
<div>
          {scenes.map((scene) => (
            <Scene
              key={Math.floor(Math.random() * 1000)}
              addText="scene #{f}id"
              onDelete={removeScene}
              value={scene}
              selected={true}
              length={scenes.length}
              switchScene={switchScene}
              saveCurrentScene={saveCurrent}
            />
          ))}
          <button onClick={addScene} className="btn btn-primary m-2">
            Add scene
          </button>
        </div>

Scene component :


function Scene(props) {
  const id = useState(_uniqueId("sceneCmpn-"));
  const { value, length, switchScene, onDelete, saveCurrentScene } = props;

  const [selected, setSelected] = useState(false);
  return (
    <div key={id}>
      <button
        id={id}
        onClick={() => {
          setSelected(true);
          switchScene(value);
        }}
      >
        Scene
      </button>
      {length > 1 && (
        <button onClick={() => onDelete(value)} className="btn btn-danger m-2">
          remove scene
        </button>
      )}
      {selected && (
        <button
          onClick={() => {
            saveCurrentScene(value);
          }}
          className="btn btn-success m-2"
        >
          Save
        </button>
      )}
    </div>
  );
}



I want to make save button appear when i click on scene button, it does work, but when i click on another scene the button stays there.

enter image description here

How can i make the green save button disappear if i switch ("click") the scene.

EDIT : this is code of switch scene, i think is not important for this problem :

const switchScene = (scene) => {
    let cpScenes = [...scenes];
    const index = scenes.indexOf(scene);
    const cpJsonObj = cpScenes[index].JsonObj;
    //console.log("this object in switchScene", cpJsonObj);
    canvas.resetEditor();
    canvas.loadJson(cpJsonObj);
    canvas.exportImg();
  };
```

Solution

  • In Editor component, you should add another state to check a selected scene.

    const [selectedScene, setSelectedScene] = useState(); 
    

    And switchScene function might be

    const switchScene = (scene) => {
        let cpScenes = [...scenes];
        const index = scenes.indexOf(scene);
        const cpJsonObj = cpScenes[index].JsonObj;
        //console.log("this object in switchScene", cpJsonObj);
        canvas.resetEditor();
        canvas.loadJson(cpJsonObj);
        canvas.exportImg();
        setSelectedScene(scene); //set state change here
    };
    

    After that, you can modify selected props of Scene from Editor

    {scenes.map((scene) => (
                <Scene
                  key={Math.floor(Math.random() * 1000)}
                  addText="scene #{f}id"
                  onDelete={removeScene}
                  value={scene}
                  selected={selectedScene === scene}
                  length={scenes.length}
                  switchScene={switchScene}
                  saveCurrentScene={saveCurrent}
                />
              ))}
    

    From all the above changes, you need to align them with Scene component

    Now selected is from props, not from state anymore

    function Scene(props) {
      const id = useState(_uniqueId("sceneCmpn-"));
      const { value, length, switchScene, onDelete, selected, saveCurrentScene } = props;
    
      return (
        <div key={id}>
          <button
            id={id}
            onClick={() => {
              switchScene(value);
            }}
          >
            Scene
          </button>
          {length > 1 && (
            <button onClick={() => onDelete(value)} className="btn btn-danger m-2">
              remove scene
            </button>
          )}
          {selected && (
            <button
              onClick={() => {
                saveCurrentScene(value);
              }}
              className="btn btn-success m-2"
            >
              Save
            </button>
          )}
        </div>
      );
    }