Javascript 通过组件传输数据
我有父组件和子(listView)组件。我的目标是将后端调度的数据从父级发送到子级。我通过点击按钮来实现这一点。问题是,在第二个父按钮单击后,子按钮将渲染。也许我的错误在Javascript 通过组件传输数据,javascript,reactjs,react-native,react-redux,Javascript,Reactjs,React Native,React Redux,我有父组件和子(listView)组件。我的目标是将后端调度的数据从父级发送到子级。我通过点击按钮来实现这一点。问题是,在第二个父按钮单击后,子按钮将渲染。也许我的错误在组件中的某个地方会收到道具 家长: class Parent extends Component { constructor(props) { super(props); this.state = { dataSource: '', noRe
组件中的某个地方会收到道具
家长:
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>
);
}
}
类父级扩展组件{
建造师(道具){
超级(道具);
此.state={
数据源:“”,
诺雷波斯:错
};
}
组件将接收道具(新道具){
这是我的国家({
数据源:newProps.data
});
这个.validateData(newProps)
}
submitUsername(){
if(this.validateInput()){
this.props.dispatch({type:'DUMMY',state:this.state.username});
}否则{
this.setState({emptyInput:true});
}
}
render(){
返回(
...
...
);
}
}
导出默认连接(状态=>{
返回{
数据:state.data,
};
})(家长);
子项:
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>
);
}
}
导出默认类ListViewComponent扩展组件{
建造师(道具){
超级(道具);
此.state={
数据源:新建ListView.dataSource({
行已更改:(r1,r2)=>r1!==r2,
}),
};
}
道具类型:{
接收的数据:PropTypes.func.string
};
组件将接收道具(新道具){
这是我的国家({
dataSource:this.state.dataSource.cloneWithRows(this.props.datareceived),
});
}
renderRow(行数据){
返回(
{rowData.name}
);
}
render(){
返回(
);
}
}
好的,一般的建议是始终保持单一的真相来源:
- 不要将道具中已有的数据复制到内部组件状态。使用道具中的数据
- 尽量创建无状态的组件(见上文…使用道具,或让组件监听“存储”。见Redux或AltJs)
特别是为了解决您的问题: 在父替换中:
<ListViewComponent dataRecieved={this.state.dataSource} />
但要做到:
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>
);
}
render(){
var ds=new ListView.DataSource({
行已更改:(r1,r2)=>r1!==r2,
})
,dataSource=ds.cloneWithRows(this.props.datareceived);
返回(
);
}
以上是未经测试的代码,但应作为遵循方法的指南。您最初实现的
ListViewComponent
很好,在刷新ListView
时,您应该使用componentWillReceiveProps
。每个最佳实践都说要这样做(只需谷歌react native redux listview
)。您只是在实现中有一个我在上面的评论中提到的小错误。另外,您不应该在呈现
函数中重新创建列表视图.DataSource
,这对性能不好,并且违背了列表视图.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),
});
}
另外,您的父级
不应在其状态下持有数据源
,只需直接将数据
传递到列表视图组件
,因为Redux已经将其作为道具
传递:
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);
类父级扩展组件{
建造师(道具){
超级(道具);
此.state={
// ...
};
}
组件将接收道具(新道具){
// ...
}
submitUsername(){
if(this.validateInput()){
this.props.dispatch({type:'DUMMY',…});
}否则{
// ...
}
}
render(){
返回(
...
{/*this.props.data自动来自下面的“connect”包装器*/}
...
);
}
}
导出默认连接(状态=>{
返回{
数据:state.data,
};
})(家长);
你也应该看看这个。这是一个如何在列表视图
旁边使用Redux的示例。他的示例使用了cloneWithRows和sections
,但因为没有sections,所以只能使用cloneWithRows
进行调整。这个要点是由一位相当活跃的core React本地开发人员编写的。1。在哪里可以看到数据副本?2.举个例子。你看这不是答案。这是一些指导原则,我认为数据复制的地方很明显。例如,在Parent
this.setState({dataSource:newProps.data})中,这是副本还是引用?它正在将props中的数据克隆到状态中。如何避免这种情况?错误在于ListViewComponent
的组件将接收props
使用this.props.dataReceived
,而不是newProps.dataReceived
。另外,请检查您的拼写,它应该是收到的
,而不是收到的
。