问题
I have a situation where I have two elements that are tied together, with a Board that non-negotiably always consists of 4 subdivision panels:
var BoardPanel = React.createClass({
getInitialState: function() {
return { someval: '' };
},
render: function() {
<div>{this.state.someval}</div>
},
doSomething: function(v) {
setState({ someval: v });
}
});
var BoardLayout = React.createClass({
render: function() {
<div>
<h1>{this.props.label{</h1>
<div ref="panels">
<BoardPanel />
<BoardPanel />
<BoardPanel />
<BoardPanel />
</div>
</div>
}
});
The BoardLayout should be able to uniformly tell each BoardPanel to call panel API functions, so I would like to do the React.js equivalent of:
this.querySelectorAll("BoardPanel")
.array()
.forEach(function(panel, idx) {
panel.doSomething(idx);
});
Note that I expressly do not want to access the DOM nodes here, I want to access the React-defined virtual elements, call functions on that, and never ever touch the actual browser-used DOM.
I had a look at the React.children utility functions, but these are fairly useless because there is no way to specify which children I want, and this.props.children
is going to give me two div
elements, since the BoardPanel
elements live "deep" inside the template.
(I'm also fairly averse to adding ref="..."
with throwaway identifiers for each BoardPanel, because there shouldn't be any need to do this, given that this is well formatted, structured markup. It's a possible workaround, but seems about as sensible as slapping ids on every element in an HTML file instead of relying on query selectors)
I could dynamically generate them by not actually having them in the template at all and adding them using React.create(BoardPanel)
in BoardLayout.getInitialState
but that would turn the immediately insightful template structure into an opaque placeholder, which is also a thing I'd rather not do.
Can I, in BoardLayout.componentDidMount
or the like, somehow get the array of BoardPanel
components used, so that I can directly instruct those components to do things? If so, how?
回答1:
If you need to do this (you probably don't), you need to use refs.
function refsToArray(ctx, prefix){
var results = [];
for (var i=0;;i++){
var ref = ctx.refs[prefix + '-' + String(i)];
if (ref) results.push(ref);
else return results;
}
}
var BoardLayout = React.createClass({
var makeRef = function(){ return 'BoardPanel-'+(_refi++); }, _refi=0;
render: function() {
<div>
<h1>{this.props.label{</h1>
<div ref="panels">
<BoardPanel ref={makeRef()} />
<BoardPanel ref={makeRef()} />
<BoardPanel ref={makeRef()} />
<BoardPanel ref={makeRef()} />
</div>
</div>
}
});
And then you would do refsToArray(this, 'BoardPanel')
to get an array of refs.
But like I said, there's probably a better solution but you didn't indicate what you're actually trying to do.
来源:https://stackoverflow.com/questions/27555667/how-does-one-select-all-child-components-not-dom-elements-used-in-a-reactjs-co