2015-12-18 11 views
5

Próbuję utworzyć niestandardowy komponent checkbox (właściwie trzy-stan, ale to nie ma znaczenia, z wyjątkiem tego, że mówię, że nie używam tylko INPUT), i nie jestem pewien, jak mogę to zrobić zmienić "sprawdzanie" na podstawie kliknięć na siebie i na zestawie wartości schodzących z rodzica.Jak zarządzać stanem na komponencie React, który może zmienić stan z elementu nadrzędnego lub zdarzenia na nim?

Obecnie pracuję jako samowystarczalny komponent, który pobiera protokół onChange z wywoływanym zwrotem procedury obsługi, który wywołuje, aby wysłać wartość komponentu nadrzędnego po kliknięciu. Używa stanu do przechowywania sprawdzania, do którego odwołuje się wyświetlacz.

Jeśli był to tylko wyświetlacz z kontrolą, z wartością zarządzaną z zewnątrz, oczywiście używałbym rekwizytów. Gdyby był to samowystarczalny element pola wyboru, który przyjąłby wartość początkową, a następnie odpowiadał tylko na kliknięcia, użyłbym stanu, tak jak ja, ale moim problemem jest to, że chcę, aby można było je włączać i wyłączać, a także pozwól rodzicowi również go włączyć i wyłączyć.

Jestem początkujący w React i "React way of thinking", więc podejrzewam, że właśnie zbliżam się do tego błędu. Odnoszę wrażenie, że właściwym sposobem na zrobienie tego będzie to, że jest to komponent tylko do wyświetlania, który przekazuje kliknięcia rodzicowi, aby mógł sobie z nim poradzić, a następnie otrzymywał aktualizacje rekwizytów dla zmian wartości od rodzica, ale to spowodowałoby, że komponent byłby o wiele mniej przydatny do ponownego użycia.

W jaki sposób chciałbym zmienić pole wyboru zarówno ze źródeł wewnętrznych, jak i macierzystych?

Odpowiednie linki są również mile widziane.

Odpowiedz

7

można traktować pole jako składnikniemych, co oznacza, że ​​nie posiada żadnych stanów wewnętrznych, ale tylko odbiera dane z zewnątrz poprzez rekwizytów a następnie czynią im. Możesz zobaczyć szczegółową definicję głupich komponentów here.

Tymczasem, gdy pole jest kliknięty, takie zdarzenia będą traktowane przez rodzica komponentu lub przodków zdarzeń, jest to tzw dane odwrotnych przepływu, który jest opisany w Facebooka Thinking in React blogu.

Ponadto, aby zdecydować, który składnik powinien posiadać pewne stany, znaleźć następujące wytyczne bardzo przydatne:

Pamiętaj: React jest o jednokierunkowy przepływ danych w dół hierarchii komponentów. Może nie być od razu jasne, który składnik powinien posiadać swój stan. To jest często największym wyzwaniem dla nowoprzybyłych do zrozumienia, więc następujące kroki, aby zrozumieć to:

Dla każdego kawałka stanu w aplikacji:

  • Zidentyfikuj każdy składnik, który czyni coś na podstawie ten stan.
  • Znajdź wspólny element właściciela (pojedynczy komponent ponad wszystkie składniki, które wymagają stanu w hierarchii).
  • Właściciel lub inny składnik znajdujący się wyżej w hierarchii powinien być właścicielem stanu.
  • Jeśli nie możesz znaleźć komponentu, w którym ma sens posiadanie stanu, utwórz nowy komponent po prostu do przechowywania stanu i dodaj go gdzieś w hierarchii nad wspólnym elementem właściciela.

Pseudo-fragment kodu:

const Checkbox = React.createClass({ 
    // Propagate the event to parents 
    onClick(evt) { 
    if (this.props.handleClick) { 
     this.props.handleClick({checked: evt.target.value}); 
    } 
    }, 

    render() { 
    return (
     this.props.checked ? 
     <Input onClick={this.onClick} type="checkbox" label="Checkbox" checked></Input> : 
     <Input onClick={this.onClick} type="checkbox" label="Checkbox"></Input> 
    ); 
    } 
}); 

const Container = React.createClass({ 
    handleClick(evt) { 
    // Change the container's state, which eventually changes the checkbox's view via props. 
    this.setState({checked: evt.checked}); 
    }, 

    render() { 
    return (
     <div><Checkbox checked={this.state.checked} handleClick={this.handleClick}></Checkbox></div> 
    ); 
    } 
}); 
+0

Tak, to brzmi jak to, co muszę zrobić. Zaczynam poruszać moje myślenie od moich starych pomysłów "brygady kubełkowej" (gdzie dane są rozpatrywane w razie potrzeby przez indywidualny komponent) do bardziej "centralnego punktu kontrolnego" pomysłu, którego używa React. Po prostu nie zdawałem sobie sprawy, że filozofia jest tak wszechogarniająca, co było moim zawieszeniem. I dzięki za linki do artykułów. – SuperFLEB

3

Zmieniasz go tylko z rodzica.

class ParentComponent extends React.Component{ 
    handleChildCheck(){ 
    this.setState({ 
    childChecked: !this.state.childChecked 
    }) 
    } 
    render(){ 
    return(
     <ChildComponent checked={this.state.childChecked} handleCheck={this.handleChildCheck.bind(this)} /> 
    ) 
} 
} 

Teraz, jeśli chcesz kontrolować sprawdzony stan z <ChildComponent/> zadzwoń this.props.handleCheck() z <ChildComponent/>

ten sposób kontrole będą zawsze dostępne wewnątrz <ChildComponent/> poprzez this.props.handleCheck() w <ParentComponent/> poprzez this.handleChildCheck().

+0

Dobra, po patrząc na to i noodling się trochę bardziej na własną rękę, myślę, że to dostać. Zasadniczo, komponent Checkbox (dziecko) powinien zajmować się tylko przyjmowaniem rekwizytów sprawdzających, wyświetlając się poprawnie jako takie i przekazując zdarzenia interakcji (kliknięć) do obsługi rodzica (handleChildCheck, w twoim przykładzie). Cała reszta, łącznie z logiką tego, w jaki sposób kliknięcie pola wyboru faktycznie ustawia rekwizyt sprawdzalności, powinna być obsługiwana przez rodzica i sprowadzać dziecko do rekwizytów. Czy to brzmi poprawnie? – SuperFLEB

+0

Tak, zgadza się. To pasuje do sposobu myślenia React! –

-2

Użyj querySelectorAll, aby znaleźć swoje komponenty. Dodaj detektor zdarzeń do monitorowania zmian. Przy zmianie uruchom inny querySelectorAll, aby znaleźć dzieci i wyłączyć lub włączyć. To może nie pokryć wszystkich twoich potrzeb, ale pozwoli ci zacząć we właściwym kierunku. Jest to prosty javascript, więc żadne inne biblioteki nie są wymagane.

// Finds radios with class on-off and disables 'name-on' elements when 
 
// 'name' is off. 
 

 
function initOfOff() { 
 
    var mains = document.querySelectorAll('.on-off'); 
 

 
    for (var i = 0; i < mains.length; i++) { 
 
    var el = mains[i]; 
 
    var name = el.getAttribute('name'); 
 
    el.addEventListener('click', function() { 
 
     var value = this.getAttribute('value'); 
 
     var children = document.querySelectorAll('.' + name + '-on'); 
 
     for (var i = 0; i < children.length; i++) { 
 
     var child = children[i]; 
 
     child.checked = false; 
 
     if (value == "off") { 
 
      child.setAttribute('disabled', 'disabled'); 
 
     } else { 
 
      child.removeAttribute('disabled'); 
 
     } 
 
     } 
 
    }); 
 
    } 
 
} 
 
initOfOff()
<form name='myform'>power 
 
    <input type='radio' value='on' class='on-off' name='power'>ON | 
 
    <input type='radio' value='off' class='on-off' name='power'>Off 
 
    <dir>lights 
 

 
    <input type='radio' value='on' class='power-on' name='lights'>ON | 
 
    <input type='radio' value='off' class='power-on' name='lights'>OFF 
 
    </dir> 
 
</form>

+0

Przepraszam, powinienem był wspomnieć, że szukam rozwiązania specyficznego dla React. (Tak naprawdę nie piszę do SO tak bardzo, więc wciąż jestem trochę rozmyta, jeśli chodzi o szczegóły dotyczące kategoryzacji.) Zmieniłem odpowiednio tagi i tytuł. Ale dzięki za to. – SuperFLEB

Powiązane problemy