Wątek przeniesiony 2024-06-04 16:39 z JavaScript przez Riddle.

Renderowanie statusu poza elementem div

0

Witam

W ramach treningu Portali w React postanowiłem rozwiązać taki problem jak renderowanie tablicy z obiektem poza elementem div poprzez utworzenie Portalu aczkolwiek sterowane przyciskiem. Sama tablica z obiektem była by przypisana do useState.
Wymyśliłem to więc w taki sposób:

  1. Utworzenie tablicy obiektów/stringow w useState
  2. Renderowanie status w div
  3. Renderowanie statusu poprzez Portal po za div

Na razie pomysł nie wychodzi, być może droga nie ta.

import { createPortal } from 'react-dom';
import { useState } from 'react';
import ReactDOM  from 'react-dom/client';

const listOfShoes = [
    {typeOfShoes : "sandals",
    brand : "Laoke",
    price : "100",
    currency : "punds"}
];
        
export function RenderArrObject(){
    var [arrOfObjects, setArrOfObjects] = useState(listOfShoes);
    
    function handleButton(){

        return(
            <ul>
                {arrOfObjects.map( content => (
            <li key={content.typeOfShoes}>
                {content.typeOfShoes}
                {content.brand}
                {content.price}
            </li>
                ))}
            </ul>
        )
        }

return(
        <div>
            <button onClick={handleButton}>Generate</button>
</div>
        
    )
}

const execute = ReactDOM.createRoot(document.getElementById('root'));
execute.render(<RenderArrObject />);

2

A gdzie tu jakiś portal jest?

Ogólnie czytałem to kilka razy i dalej nie mogę zrozumieć co w ogóle chcesz osiągnąć.

Pokaż jakąś stronę która robi to samo, albo narysuj w paincie.

Na pewno ten callback, który zwraca elementy JSX (z którymi nic się nie wydarzy) zalatuje mi programowaniem imperatywnym. Wydaje mi się, że nie łapiesz idei Reacta jeszcze, a już bierzesz się za rzeczy zaawansowane.

0

"Wydaje mi się, że nie łapiesz idei Reacta jeszcze"
Zgadzam się z przedmówcą.

arrOfObjects - po prostu zrenderuj tabele/liste z zawartością.
Przycisk generate jest w zasadzie zbędny. handleButton nie powinien zwracać html'a

Jeżeli bardzo chcesz przycisk generate, to możesz spróbować.

var [arrOfObjects, setArrOfObjects] = useState([])  // inicjalizacja pusta lista


function handleButton(){
  setArrOfObjects(listOfShoes)  // zmienisz stan wiec component sie przerenderuje

}

return(<>
        <div>
            <button onClick={handleButton}>Generate</button>
      </div>
      <ul>... dane co chcesz zaprezentować </ul>
</>)
0

Podzieliłem ten problem na mniejsze dlatego wypisałem kroki na samej górze Najpierw chce zrenderować listę w div, potem utworzyć portal do aby po użyciu przycisku lista wyświetliła się w body dokumentu. Portale nie są łatwe, ale hook typu useState nie jest aż tak skomplikowany. Chciałem zobaczyć czy da się połączyć te dwie rzeczy. Równie dobrze można by próbować z obiektem state. Co nieco Reacta już przepracowałem więc sądzę, że taki ,,laik" ze mnie nie jest. Pytanie jaki mielibyście pomysł na rozwiązanie tego problemu.

Renderujemy obiekt w paragrafie, same dane pobieramy ze statusu zarzadzając tym z poziomu przycisku.

0

https://react.dev/reference/react-dom/createPortal

import { createPortal } from 'react-dom';

export default function MyComponent() {
  return (
    <div style={{ border: '2px solid black' }}>
      <p>This child is placed in the parent div.</p>
      {createPortal(
        <p>This child is placed in the document body.</p>,
        document.body
      )}
    </div>
  );
}

Zamiast paragrafu miej swój komponent który prezentuje dane.
use state do zapisania stanu czy przycisk został kliknięty
Na podstawie stanu można warunkowo tworzyć część create portal.

      {warunek && createPortal(   // jeśli warunek/boolean zwróci false to createPortal nie będzie wykonywane/renderowane
        <p>This child is placed in the document body.</p>,
        document.body
      )}

0

Po prawie 3h prób szybkiej edukacji z warunków udało się skonstruować coś takiego co nawet spełnia zasady czystego kodu. Nie jestem pewien czy krsp miał to na myśli. Prościej się chyba nie da tego ująć :

import {useState} from 'react';
import ReactDOM  from 'react-dom/client';
import { createPortal } from 'react-dom';

export function CheckTheState(){

    const[componentState, setComponentState] = useState("State of component");
    const[btnState, setState] = useState(false);


    function checkBtnState(){
        setState(true);
        
        <RenderOutsideComponent />
    }

    function ComponentToTeleport(){

        return(
            <p>{componentState}</p>
            
        )
    }

    function RenderOutsideComponent(){

        if(btnState)
        {
            return(
                <div>
                    
                    {btnState && createPortal(
                    <ComponentToTeleport />, document.body)
                    }
                    
                </div>
            )
        }
    }

    return(
        <div>
            <button onClick={checkBtnState}>Action</button>
            <RenderOutsideComponent />
        </div>
        
    )
}

const execute = ReactDOM.createRoot(document.getElementById('root'));
execute.render(<CheckTheState />);

Co do nauki to co na razie wyznaje zasadę. Nie znasz pewnego elementu kodu daj sobie ze 3 dni i pobaw się trochę zagadnieniem aczkolwiek czasem czlowiek albo wymyśli problem zbyt skomplikowany albo zbyt odejdzie od koncepcji zagadnienia. Dokumentacja daje trochę dobrych przykładów które można przerobić, ale tutaj istotna kreatywność.

0

To miałem na myśli.
Bardziej rzucące się w oczy rzeczy:

    function checkBtnState(){
        setState(true);
        
        <RenderOutsideComponent />
    }

Na podstawie tego kodu, są pytania odnośnie wyczucia użycia reacta.
RenderOutsideComponent jest totalnie zbędny i nic nie robi. Teraze tez nazwa funkcji jest myląca bo ona nic nie sprawdza. Ona ustawia stan żeby na jego podstawie wyrenderować z użyciem create portal. Jesze bym dodał możliwość zmieniania z powrotem tej flagi (toggle).

    function checkBtnState(){
        setState(prevState => !prevState);
    }

W RenderOutsideComponent if(btnState) jest zbędny (duplikuje sprawdzenie)

    function RenderOutsideComponent(){
            return(
                <div>
                    {btnState && createPortal(
                        <ComponentToTeleport />, document.body)
                    }

                </div>
            )
    }

Ja osobiście nie zadnieżdżam implementacji komponentów i preferuje coś w stylu:

import {useState} from 'react';
import ReactDOM from 'react-dom/client';
import {createPortal} from 'react-dom';

export function CheckTheState() {

    const [btnState, setState] = useState(false);

    function checkBtnState() {
        setState(prevState => !prevState);
    }

    return (
        <div>
            <button onClick={checkBtnState}>Action</button>
            <RenderOutsideComponent btnState={btnState}/>
        </div>

    )
}

function RenderOutsideComponent(props) {
    const btnState = props.btnState;

    return (
        <div>
            {btnState && createPortal(
                <ComponentToTeleport/>, document.body)
            }
        </div>
    )
}

function ComponentToTeleport() {
    const [componentState, setComponentState] = useState("State of component");

    return (
        <p>{componentState}</p>

    )
}


const execute = ReactDOM.createRoot(document.getElementById('root'));
execute.render(<CheckTheState/>);

1 użytkowników online, w tym zalogowanych: 0, gości: 1