两个子组件之间的通信,而不会在父

时间:2016-07-08 08:56:39

标签: reactjs

我一直在学习和使用ReactJS。在阅读了大量的主题和博客文章后,我仍然对在ReactJS中组件之间进行有效沟通感到困惑。

让我们说我是一个父母组件" A"它有许多子组件" a"," b"," c"," d"," e"现在,事情发生在" a"组件,我想重新渲染" b"零件。

因为" a"和" b"我有同样的父母,我可以使用父母本身作为这两者之间的沟通媒介。但问题在于,当我使用parent作为通信媒介时,它会改变它的状态并触发重新渲染,并且会导致重新渲染所有组件" a" ," c"," d"," e"我不喜欢它,而是我想强行重新渲染" b"零件。

这可能吗?我怎样才能做到这一点?基本上我想出于性能原因这样做。

2 个答案:

答案 0 :(得分:1)

有一种方法可以做到这一点,但是......

JavaScript如果快速和React协调算法也非常快。 React不会重新渲染DOM,只会检查其他组件是否有变化,如果存在则应用。

你可以做你想要的。为此你有shouldComponentUpdate函数,在渲染之前调用它。因此,如果为子组件实现此功能,则不会重新呈现它们。但是,建议仅使用此功能才能确实存在性能问题。

如果子组件很简单且没有深层的对象树,则可以使用shallow compare辅助函数。将来,它有可能默认包含在所有pure组件中。

答案 1 :(得分:0)

使用普通的React是完全可行的。您的父组件需要充当容器并保持与其子项的props相对应的状态。当其中一个子项触发更新时,如果您实现shouldComponentUpdate方法,则其他子项将不会重新呈现。这是一个工作片段,如果您选中/取消选中第一个列表中的某个项目,则所有三个项目都将重新呈现。在下面的第二个列表中,只有目标项目会重新渲染。

class ItemsList extends React.Component {
    
    constructor(props) {
        super(props)
        this.state = {
            items: {
                a: false,
                b: false,
                c: true
            }
        }
    }

    render() {
        const self = this
        return (
            <ul>
                {Object.keys(self.state.items).map(
                    id => (
                        <Item
                            key={id}
                            id={id}
                            checked={self.state.items[id]}
                            handleChange={(e) => {
                                e.persist()
                                this.setState(state => ({
                                    ...self.state,
                                    items: {
                                        ...self.state.items,
                                        [id]: e.target.checked
                                    }
                                }))
                            }}/>
                    )
                )}
            </ul>
        )
    }
}


class Item extends React.Component {

    shouldComponentUpdate(nextProps) {
        return nextProps.checked != this.props.checked
    }

    render() {
        console.log(`rendering ${this.props.id}`)
        return (
            <li>
                <span>{this.props.id}</span>
                <input
                    type="checkbox"
                    checked={this.props.checked}
                    onChange={this.props.handleChange}/>
            </li>
        )
    }
}

class ItemsList2 extends React.Component {
    
    constructor(props) {
        super(props)
        this.state = {
            items: {
                a: false,
                b: false,
                c: true
            }
        }
    }

    render() {
        const self = this
        return (
            <ul>
                {Object.keys(self.state.items).map(
                    id => (
                        <Item2
                            key={id}
                            id={id}
                            checked={self.state.items[id]}
                            handleChange={(e) => {
                                e.persist()
                                this.setState(state => ({
                                    ...self.state,
                                    items: {
                                        ...self.state.items,
                                        [id]: e.target.checked
                                    }
                                }))
                            }}/>
                    )
                )}
            </ul>
        )
    }
}


class Item2 extends React.Component {

    render() {
        console.log(`rendering ${this.props.id}`)
        return (
            <li>
                <span>{this.props.id}</span>
                <input
                    type="checkbox"
                    checked={this.props.checked}
                    onChange={this.props.handleChange}/>
            </li>
        )
    }
}

ReactDOM.render(<ItemsList/>, document.getElementById('app2'))

ReactDOM.render(<ItemsList2/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.0/react.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.2.0/react-dom.js"></script>
<script src="https://wzrd.in/standalone/react-addons-perf@latest"></script>
<div id="app"></div>
<div id="app2"></div>