我有父组件和子组件(listView)组件。我的目标是将后端调度的数据从父节点发送到子节点。我通过按钮点击实现了这一点。问题是孩子在第二次父按钮点击后呈现。也许我的错误出现在componentWillReceiveProps
?
父:
class Parent extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: '',
noRepos: false
};
}
componentWillReceiveProps(newProps) {
this.setState({
dataSource: newProps.data
});
this.validateData(newProps)
}
submitUsername() {
if(this.validateInput()){
this.props.dispatch({type: 'DUMMY', state: this.state.username});
} else {
this.setState({emptyInput: true});
}
}
render() {
return (
...
<View>
<ListViewComponent dataRecieved={this.state.dataSource} />
</View>
...
);
}
}
export default connect(state => {
return {
data: state.data,
};
})(Parent);
儿童:
export default class ListViewComponent extends Component {
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
}),
};
}
propTypes: {
dataRecieved: PropTypes.func.string
};
componentWillReceiveProps(newProps) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.props.dataRecieved),
});
}
renderRow(rowData) {
return (
<View>
<Text>{rowData.name}</Text>
</View>
);
}
render() {
return (
<View>
<ListView dataSource={this.state.dataSource}
enableEmptySections={true}
renderRow={this.renderRow} />
</View>
);
}
}
答案 0 :(得分:1)
好的,一般建议是始终保持单一的事实来源:
不要将您在props中已有的数据复制到内部组件状态。使用道具中的数据。
尝试尽可能无状态地创建您的组件(请参阅上文...使用道具,或让组件收听&#39;存储&#39;。请参阅Redux或AltJs。)
专门尝试解决您的问题:
在父母替换中:
<ListViewComponent dataRecieved={this.state.dataSource} />
与
<ListViewComponent dataRecieved={this.props.data} />
在ListViewComponent中,不要这样做:
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.props.dataRecieved),
});
但是:
render() {
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
})
, dataSource = ds.cloneWithRows(this.props.dataRecieved);
return (
<View>
<ListView dataSource={dataSource}
enableEmptySections={true}
renderRow={this.renderRow} />
</View>
);
}
以上是未经测试的代码,但应作为指导方法的指南。
答案 1 :(得分:1)
您最初实施var wikipedia = require("node-wikipedia");
var infobox = require('wiki-infobox');
var Promise = require('es6-promise').Promise;
var fs = require('fs');
String.prototype.format = function()
{
var content = this;
for (var i=0; i < arguments.length; i++)
{
var replacement = '{' + i + '}';
content = content.replace(replacement, arguments[i]);
}
return content;
};
function getLinks() {
return new Promise(function(resolve, reject) {
wikipedia.page.data("List_of_hip_hop_musicians", { content: true }, function(response) {
fs.writeFile("response.json", JSON.stringify(response, null, 2), function(err) {
if(err) {
return console.log(err);
}
});
resolve(response.links);
});
});
}
function getInfo(links){
return new Promise(function(resolve, reject) {
fs.appendFile("info.csv", "name, background, birth_name, birth_date, birth_place, origin, genre, occupation, instrument, years_active, label, website\n", function(err) {
if(err) {
return console.log(err);
}
});
for (i=0; i<10; i++) {
var link = links[i]['*'];
resolveInfo(link).then(function(newText){
fs.appendFile("info.csv", newText, function(err) {
if(err) {
return console.log(err);
}
});
});
}
resolve(text)
});
}
function resolveInfo(link) {
return new Promise(function(resolve, reject) {
infobox(link, 'en', function(err, data){
if (err) {
return console.log(err);
}
try {
var text = '{0}, {1}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}\n'.format(data.name.value, data.background.value, data.birth_name.value, data.birth_date.value, JSON.stringify(data.birth_place), data.origin.value, data.genre.text, JSON.stringify(data.occupation), data.instrument.text, data.years_active.value, data.label.value, data.website.value);
} catch(err){
var text = "";
}
resolve(text);
});
});
}
getLinks().then(function(links) {
getInfo(links).then(function(text){
});
});
的方式很好,在刷新ListViewComponent
时,您应该使用componentWillReceiveProps
。那里的每一个最佳实践都说要做到这一点(只有Google ListView
)。您在上面的评论中提到的实施中只是略有错误。此外,不应该重新创建react native redux listview
函数中的ListView.DataSource
,这对性能不利,并且在render
中违背了rowHasChanged
的目的}。
我所说的错误就在这里:
ListView.DataSource
它应该是:
componentWillReceiveProps(newProps) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.props.dataRecieved),
});
}
此外,您的// ListViewComponent
componentWillReceiveProps(newProps) {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(newProps.dataRecieved),
});
}
不应在其Parent
中持有dataSource
,只需将state
直接传递到data
,因为Redux会将其作为ListViewComponent
传递给prop
已经class Parent extends Component {
constructor(props) {
super(props);
this.state = {
// ...
};
}
componentWillReceiveProps(newProps) {
// ...
}
submitUsername() {
if (this.validateInput()) {
this.props.dispatch({ type: 'DUMMY', ... });
} else {
// ...
}
}
render() {
return (
...
<View>
{/* this.props.data automatically comes from the `connect` wrapper below */}
<ListViewComponent dataRecieved={this.props.data} />
</View>
...
);
}
}
export default connect(state => {
return {
data: state.data,
};
})(Parent);
:
ListView
您还应该看看这个gist。这是如何将Redux与cloneWithRowsAndSections
一起使用的示例。他的示例使用cloneWithRows
,但由于您没有部分,因此您只需使用public function Person_name($person_code)
{
$code= explode(',', $person_code);
$name=array();
for($i=0; $i<count($code); $i++){
$sql= Yii::app()->db->createCommand('select nm_person from tbl_person where kd_person="'.$code[$i].'";');
$name=$sql->queryRow();
}
$namearray= implode(',',$name);
return $namaarray;
}
进行调整。这个要点是由一个非常活跃的核心React Native开发人员编写的。