是否可以直接从它的低阶组件将数据传递给 withTracker ?
Is it possible to pass data up to withTracker directly from it's lower order component?
我在使用 React、Meteor 和 react-meteor-data 组合的现有代码库中工作。
在我尝试使用 withTracker 实现搜索功能之前,一切都比较顺利,
React Select,
和 Meteor 的订阅功能。
import { CollectionAPI } from '../arbitrary_meteormongo_collection';
export const WriteableConnectionToCollection = withTracker(props => {
let connection = Meteor.subscribe('COLLECTION_NAME.searchByName', SEARCH_TEXT_HERE);
let isLoading = connection.ready();
return {
...props,
isLoading: isLoading,
collection: CollectionAPI.find().fetch()
}
})(PRESENTATIONAL_COMPONENT);
我在谷歌上搜索了一下,发现将数据获取到 Meteor.subscribe 的常见解决方案是使用 URL 参数之类的东西,但由于我在现有代码库中工作,因此此更改会也需要在不同的地方实施。
我发现的另一种方法是通过跟踪父组件状态中的输入字段状态将输入字段的值传递给父组件,尽管这显然违反了关注点分离的原则:
父组件
export const ParentComponent = React.createClass({
getInitialState() {
return {
inputFieldValue: undefined
}
},
onChange(change) {
this.setState(inputFieldValue);
},
render() {
return (
<Search
onChange={this.onChange}
inputFieldValue={this.state.inputFieldValue}
/>
}
}
withTracker HOC
import { CollectionAPI } from '../arbitrary_meteormongo_collection';
export const WriteableConnectionToCollection = withTracker(props => {
let connection = Meteor.subscribe('COLLECTION_NAME.searchByName', this.props.inputFieldValue);
let isLoading = connection.ready();
return {
...props,
isLoading: isLoading,
collection: CollectionAPI.find().fetch()
}
});
输入字段组件
import { WriteableConnectionToCollection } from './connections/writeableconnection.js';
const InputFieldComponent = React.createClass({
render() {
<InputField
onInputChange={this.props.onChange}
/>
}
}
export default WritableConnectionToCollection(InputFieldComponent);
这是处理这个特定 package/framework 组合的唯一方法还是有更简单的方法我只是没看到?
正如 在我原来的问题下的评论中,我可以使用 ReactiveVar 来将输入传入和传出我的连接组件:
export const WritableConnection = function (subscriptionName, collectionAPI) {
/**
* ReactiveVar must be outside of withTracker. If the it was inside withTracker's scope,
* anytime a user would use .set(ANY_VALUE), it would overwrite whatever was in it first,
* and then re-initialize.
**/
const input = new ReactiveVar(undefined);
return withTracker(props => {
const connection = Meteor.subscribe(subscriptionName, input.get());
const isLoading = connection.ready();
return {
...props,
isLoading: isLoading,
collection: collectionAPI.find().fetch(),
setSearchText: (text) => input.set(text),
getSearchText: () => input.get()
}
})
}
我在使用 React、Meteor 和 react-meteor-data 组合的现有代码库中工作。
在我尝试使用 withTracker 实现搜索功能之前,一切都比较顺利, React Select, 和 Meteor 的订阅功能。
import { CollectionAPI } from '../arbitrary_meteormongo_collection';
export const WriteableConnectionToCollection = withTracker(props => {
let connection = Meteor.subscribe('COLLECTION_NAME.searchByName', SEARCH_TEXT_HERE);
let isLoading = connection.ready();
return {
...props,
isLoading: isLoading,
collection: CollectionAPI.find().fetch()
}
})(PRESENTATIONAL_COMPONENT);
我在谷歌上搜索了一下,发现将数据获取到 Meteor.subscribe 的常见解决方案是使用 URL 参数之类的东西,但由于我在现有代码库中工作,因此此更改会也需要在不同的地方实施。
我发现的另一种方法是通过跟踪父组件状态中的输入字段状态将输入字段的值传递给父组件,尽管这显然违反了关注点分离的原则:
父组件
export const ParentComponent = React.createClass({
getInitialState() {
return {
inputFieldValue: undefined
}
},
onChange(change) {
this.setState(inputFieldValue);
},
render() {
return (
<Search
onChange={this.onChange}
inputFieldValue={this.state.inputFieldValue}
/>
}
}
withTracker HOC
import { CollectionAPI } from '../arbitrary_meteormongo_collection';
export const WriteableConnectionToCollection = withTracker(props => {
let connection = Meteor.subscribe('COLLECTION_NAME.searchByName', this.props.inputFieldValue);
let isLoading = connection.ready();
return {
...props,
isLoading: isLoading,
collection: CollectionAPI.find().fetch()
}
});
输入字段组件
import { WriteableConnectionToCollection } from './connections/writeableconnection.js';
const InputFieldComponent = React.createClass({
render() {
<InputField
onInputChange={this.props.onChange}
/>
}
}
export default WritableConnectionToCollection(InputFieldComponent);
这是处理这个特定 package/framework 组合的唯一方法还是有更简单的方法我只是没看到?
正如
export const WritableConnection = function (subscriptionName, collectionAPI) {
/**
* ReactiveVar must be outside of withTracker. If the it was inside withTracker's scope,
* anytime a user would use .set(ANY_VALUE), it would overwrite whatever was in it first,
* and then re-initialize.
**/
const input = new ReactiveVar(undefined);
return withTracker(props => {
const connection = Meteor.subscribe(subscriptionName, input.get());
const isLoading = connection.ready();
return {
...props,
isLoading: isLoading,
collection: collectionAPI.find().fetch(),
setSearchText: (text) => input.set(text),
getSearchText: () => input.get()
}
})
}