Programing

반응에서 형제 구성 요소의 상태를 쉽게 설정하는 방법

c10106 2022. 3. 20. 12:30
반응형

반응에서 형제 구성 요소의 상태를 쉽게 설정하는 방법

선택 요소를 구동하는 데 사용할 클릭 가능한 목록 구성 요소의 시작점을 얻었다.아래에서도 알 수 있듯이onClickListItem, 아이 원소의 상태를 지나가고 있다().ListItem(이 경우) 부모에게 (이 경우)SelectableList그리고CustomSelect구성 요소.이것은 잘 작동한다.그러나 ListItem 중 하나를 클릭했을 때 선택한 상태를 전환하도록 형제 구성 요소(다른 ListItems)의 상태를 변경하는 것도 하고 싶다.

지금, 난 그저document.querySelectorAll('ul.cs-select li)클릭된 인덱스와 일치하지 않을 때 요소를 잡고 클래스를 선택한 클래스로 변경ListItem이것은 어느 정도 효과가 있다.그러나 클릭 몇 번을 해도 리액션(클라이언트 측 JS만 해당)에 의해 컴포넌트의 상태가 업데이트되지 않아, 사태가 결렬되기 시작한다.내가 하고 싶은 것은 변화시키는 것이다.this.state.isSelected형제 목록 항목을 선택하고 이 상태를 사용하여 SelectableList 구성 요소를 새로 고치십시오.내가 아래에 쓴 것에 대해 더 나은 대안을 제시할 수 있는 사람이 있을까?

var React = require('react');
var SelectBox = require('./select-box');

var ListItem = React.createClass({
    getInitialState: function() {
        return {
            isSelected: false
        };
    },

    toggleSelected: function () {
        if (this.state.isSelected == true) {
            this.setState({
                isSelected: false
            })
        } else {
            this.setState({
                isSelected: true
            })
        }
    },

    handleClick: function(listItem) {
        this.toggleSelected();
        this.props.onListItemChange(listItem.props.value);

        var unboundForEach = Array.prototype.forEach,
            forEach = Function.prototype.call.bind(unboundForEach);

        forEach(document.querySelectorAll('ul.cs-select li'), function (el) {

            // below is trying to 
            // make sure that when a user clicks on a list
            // item in the SelectableList, then all the *other*
            // list items get class="selected" removed.
            // this works for the first time that you move through the 
            // list clicking the other items, but then, on the second
            // pass through, starts to fail, requiring *two clicks* before the
            // list item is selected again.
            // maybe there's a better more "reactive" method of doing this?

            if (el.dataset.index != listItem.props.index && el.classList.contains('selected') ) {
                el.classList.remove('selected');
            }
        });
    },

    render: function() {
        return (
            <li ref={"listSel"+this.props.key}
                data-value={this.props.value}
                data-index={this.props.index}
                className={this.state.isSelected == true ? 'selected' : '' } 
                onClick={this.handleClick.bind(null, this)}>
                {this.props.content}
            </li>
        );
    }
});

var SelectableList = React.createClass({

    render: function() {

        var listItems = this.props.options.map(function(opt, index) {
            return <ListItem key={index} index={index} 
                        value={opt.value} content={opt.label}
                        onListItemChange={this.props.onListItemChange.bind(null, index)} />;
        }, this);

        return <ul className="cs-select">{ listItems }</ul>;
    }

})

var CustomSelect = React.createClass({

    getInitialState: function () {
        return {
            selectedOption: ''
        }
    },

    handleListItemChange: function(listIndex, listItem) {
        this.setState({
            selectedOption: listItem.props.value
        })
    },

    render: function () {

        var options = [{value:"One", label: "One"},{value:"Two", label: "Two"},{value:"Three", label: "Three"}];

        return (
            <div className="group">
                <div className="cs-select">
                    <SelectableList options={options} 
                        onListItemChange={this.handleListItemChange} />
                    <SelectBox className="cs-select" 
                        initialValue={this.state.selectedOption} 
                        fieldName="custom-select" options={options}/>
                </div>
            </div>
        )
    } 
})

module.exports = CustomSelect;

부모 구성요소는 자녀에게 콜백을 전달해야 하며, 각 자녀는 상태가 변경될 때 콜백을 트리거한다.여러분은 사실 모든 상태를 부모에게 붙잡아 하나의 진리로 사용하면서, "선택된" 값을 각 아이에게 소품으로 전달할 수 있다.

그럴 경우 아이는 다음과 같이 보일 수 있다.

var Child = React.createClass({
    onToggle: function() {
        this.props.onToggle(this.props.id, !this.props.selected);
    },

    render: function() {
        return <button onClick={this.onToggle}>Toggle {this.props.label} - {this.props.selected ? 'Selected!' : ''}!</button>;
    }
});

주(州)도 없고 그냥 발포만 하고onToggle클릭 시 콜백부모는 이렇게 보일 것이다.

var Parent = React.createClass({
    getInitialState: function() {
        return {
            selections: []
        };
    },
    onChildToggle: function(id, selected) {
        var selections = this.state.selections;

        selections[id] = selected;

        this.setState({
            selections: selections
        });
    },

    buildChildren: function(dataItem) {
        return <Child
            id={dataItem.id}
            label={dataItem.label}
            selected={this.state.selections[dataItem.id]}
            onToggle={this.onChildToggle} />
    },

    render: function() {
        return <div>{this.props.data.map(this.buildChildren)}</div>
    }
});

일련의 선택 항목을 상태 그대로 유지하고 있으며, 어린이의 콜백을 처리할 때는setState그 상태를 그대로 전하여 아이들을 재탕하다selected어린이 한 명 한 명 한 명 한 명 한 명 한 명 한 명 한 명 한 명씩

여기에서는 이것의 실제 예를 볼 수 있다.

https://jsfiddle.net/fth25erj/

형제간 의사소통을 위한 또 다른 전략은 관찰자 패턴을 이용하는 것이다.

Observer Pattern은 객체가 여러 개의 다른 객체에 메시지를 보낼 수 있는 소프트웨어 설계 패턴이다.

이 전략을 사용하는 데 형제 또는 부모-자녀 관계가 필요하지 않다.

반응의 맥락 안에서, 이것은 특정 메시지를 받기 위해 구독하는 일부 구성요소와 해당 구독자에게 메시지를 게시하는 다른 구성요소를 의미한다.

구성 요소는 일반적으로 구성 요소DidMount 메서드에 가입하고 구성 요소WillUnmount 메서드에 가입을 취소한다.

여기 옵서버 패턴을 구현하는 4개의 라이브러리가 있다.그들 사이의 차이는 미묘하다 - EventEmitter가 가장 인기가 있다.

  • PubSubJS: "JavaScript로 작성된 주제 기반 게시/구독 라이브러리"
  • EventEmitter: "브라우저용 이벤트 JavaScript."그것은 실제로 nodejs core의 일부로서 존재하는 라이브러리의 구현이지만 브라우저를 위한 것이다.
  • MicroEvent.js: "이벤트 이미터 마이크로라이브러리 - 20라인 - 노드 및 브라우저용"
  • mobx: "간단하고 확장 가능한 상태 관리"

다음에서 취함: Reaction 컴포넌트 통신을 위한 8가지 No-Flux 전략(일반적으로 잘 읽힌다).

다음 코드는 내가 두 형제 사이의 통신을 설정하는데 도움을 준다.설정은 렌더() 및 구성 요소디드마운트() 호출 중에 상위 항목에서 수행된다.

class App extends React.Component<IAppProps, IAppState> {
    private _navigationPanel: NavigationPanel;
    private _mapPanel: MapPanel;

    constructor() {
        super();
        this.state = {};
    }

    // `componentDidMount()` is called by ReactJS after `render()`
    componentDidMount() {
        // Pass _mapPanel to _navigationPanel
        // It will allow _navigationPanel to call _mapPanel directly
        this._navigationPanel.setMapPanel(this._mapPanel);
    }

    render() {
        return (
            <div id="appDiv" style={divStyle}>
                // `ref=` helps to get reference to a child during rendering
                <NavigationPanel ref={(child) => { this._navigationPanel = child; }} />
                <MapPanel ref={(child) => { this._mapPanel = child; }} />
            </div>
        );
    }
}

참조URL: https://stackoverflow.com/questions/30845910/how-do-i-set-state-of-sibling-components-easily-in-react

반응형