Javascript 在React.js中的组件之间传递Ajax/服务数据

Javascript 在React.js中的组件之间传递Ajax/服务数据,javascript,ajax,reactjs,Javascript,Ajax,Reactjs,我试图传递React应用程序的一个组件中接收到的数据。成功后,我将获取接收到的数据并设置状态,然后尝试将该数据作为下一个组件的属性传递。进入第二个组件后,我需要通过this.state访问传递的数据,以便稍后更改该组件中的状态。在从服务接收数据之前,我似乎遇到了DOM呈现的问题。我尝试在中传递一个已经加载的值数组来代替中的this.state.data,它似乎执行得很好。如何确保在呈现DOM之前已从服务接收到数据,以便将数据一直传递到每个组件 编辑:添加了List元素的完整实现,因此解释this

我试图传递React应用程序的一个组件中接收到的数据。成功后,我将获取接收到的数据并设置状态,然后尝试将该数据作为下一个组件的属性传递。进入第二个组件后,我需要通过
this.state
访问传递的数据,以便稍后更改该组件中的状态。在从服务接收数据之前,我似乎遇到了DOM呈现的问题。我尝试在
中传递一个已经加载的值数组来代替
中的
this.state.data
,它似乎执行得很好。如何确保在呈现DOM之前已从服务接收到数据,以便将数据一直传递到每个组件

编辑:添加了List元素的完整实现,因此解释this.state的用法

这基本上就是我要做的:

var Box = React.createClass({

  getInitialState: function() {
    return {data: []};
  },

  loadTodosFromServer: function() {
    $.ajax({
      url: this.props.url,
      dataType: 'json',
      type: 'GET',
      cache: false,
      success: function(dataResponse) {
        this.setState({data: dataResponse});
      }.bind(this),
      error: function(xhr, status, err) {
        console.error(this.props.url, status, err.toString());
      }.bind(this)
    });
  },

  componentDidMount: function() {
    this.loadFromServer();
  },

  render: function() {
    return (<List data={this.state.data}/>);
  }
});


var List = React.createClass({

  getInitialState: function() {
    return {data: this.props.data};
  },

dragStart: function(e) {
  this.dragged = e.currentTarget;
  e.dataTransfer.effectAllowed = 'move';
  // Firefox requires dataTransfer data to be set
  e.dataTransfer.setData("text/html", e.currentTarget);
},

dragEnd: function(e) {
  this.dragged.style.display = "block";
  this.dragged.parentNode.removeChild(placeholder);
  // Update data
  var data = this.state.data;
  var from = Number(this.dragged.dataset.id);
  var to = Number(this.over.dataset.id);
  if(from < to) to--;
  if(this.nodePlacement == "after") to++;
  data.splice(to, 0, data.splice(from, 1)[0]);
  this.setState({data: data});
},

dragOver: function(e) {
  e.preventDefault();
  this.dragged.style.display = "none";
  if(e.target.className == "placeholder") return;
  this.over = e.target;
  // Inside the dragOver method
  var relY = e.clientY - this.over.offsetTop;
  var height = this.over.offsetHeight / 2;
  var parent = e.target.parentNode;

  if(relY > height) {
    this.nodePlacement = "after";
    parent.insertBefore(placeholder, e.target.nextElementSibling);
  }
  else if(relY < height) {
    this.nodePlacement = "before"
    parent.insertBefore(placeholder, e.target);
  }
},

  render: function() {
    var results = this.state.data;
      return (
        <ul>
            {
              results.map(function(result, i) {
                return (
                  <li key={i}>{result}</li>
                )
              })
            }
        </ul>
      );
    }
  });


ReactDOM.render(
  <Box url="/api/comments"/>, document.getElementById('content')
);
var-Box=React.createClass({
getInitialState:函数(){
返回{data:[]};
},
loadTodosFromServer:函数(){
$.ajax({
url:this.props.url,
数据类型:“json”,
键入:“GET”,
cache:false,
成功:功能(数据响应){
this.setState({data:dataResponse});
}.绑定(此),
错误:函数(xhr、状态、错误){
console.error(this.props.url,status,err.toString());
}.绑定(此)
});
},
componentDidMount:function(){
这是loadFromServer();
},
render:function(){
返回();
}
});
var List=React.createClass({
getInitialState:函数(){
返回{data:this.props.data};
},
dragStart:函数(e){
this.drad=e.currentTarget;
e、 dataTransfer.effectAllowed='move';
//Firefox需要设置数据传输数据
e、 setData(“text/html”,例如currentTarget);
},
绘图:功能(e){
this.dradded.style.display=“block”;
this.dragged.parentNode.removeChild(占位符);
//更新数据
var data=this.state.data;
var from=Number(this.draugd.dataset.id);
var to=Number(this.over.dataset.id);
如果(从<到)到--;
如果(this.nodePlacement==“after”)到++;
数据拼接(到,0,数据拼接(从,1)[0]);
this.setState({data:data});
},
德拉戈弗:功能(e){
e、 预防默认值();
this.dradded.style.display=“无”;
if(e.target.className==“占位符”)返回;
这个。超过=e。目标;
//在dragOver方法内部
var Relay=e.clientY—this.over.offsetTop;
var height=this.over.offsetHeight/2;
var parent=e.target.parentNode;
如果(依赖>高度){
this.nodePlacement=“after”;
parent.insertBefore(占位符,例如target.nextElementSibling);
}
否则如果(依赖<高度){
this.nodePlacement=“before”
parent.insertBefore(占位符,例如target);
}
},
render:function(){
var结果=this.state.data;
返回(
    { 结果.映射(函数(结果,i){ 返回(
  • {result}
  • ) }) }
); } }); ReactDOM.render( ,document.getElementById('content')) );
组件加载后的数据加载未呈现数据的原因是列表中的这一行。呈现函数:

var results = this.state.data;
实际上,您已经复制了原始道具,并使用getInitialState方法将它们分配给列表组件中的状态。然后你的状态和道具就脱钩了。这意味着,如果列表组件上的props.data发生更改,则状态不知道它,因此不会重新呈现任何内容

因此,与其使用state初始化results变量,不如使用props

var results = this.props.data
下面是它的样子:

var List = React.createClass({

  render: function() {
    var results = this.props.data;
      return (
        <ul>
            {
              results.map(function(result, i) {
                return (
                  <li key={i}>{result}</li>
                )
              })
            }
        </ul>
      );
    }
  });
执行此操作后,react将为您重新呈现列表

另一个更新:为了说明这是如何工作的,我放了一个例子

下面是这方面的JS代码:

let todos = ["Run","Swim","Skate"];

class MyList extends React.Component{
  componentWillMount() {
    console.log("Props are: ", this.props);
    this.setState({list: this.props.items});
  }

  componentWillReceiveProps(newProps) {
    console.log("Received Props are: ", newProps);
    this.setState({list: newProps.items});
  }

  render() {
    return (<ul>
            {this.state.list.map((todo) => <li>{todo}</li>)}
            </ul>);
  }
}

class App extends React.Component{
  constructor() {
      super();
      console.log("State is: ", this.state);
  }

  componentWillMount() {
    this.setState({items: ["Fly"]});
  }

  componentDidMount() {
    setTimeout(function(){
      console.log("After 2 secs");
      this.setState({items: todos});
    }.bind(this), 2000);
  }

  render() {
      return (<MyList items={this.state.items}/>);
  }
}


ReactDOM.render(<App/>, document.getElementById("app"));
let todos=[“跑”、“游”、“滑”];
类MyList扩展了React.Component{
组件willmount(){
log(“Props是:”,this.Props);
this.setState({list:this.props.items});
}
组件将接收道具(新道具){
log(“收到的道具是:”,newProps);
this.setState({list:newProps.items});
}
render(){
返回(
    {this.state.list.map((todo)=>
  • {todo}
  • )}
); } } 类应用程序扩展了React.Component{ 构造函数(){ 超级(); log(“状态为:”,this.State); } 组件willmount(){ this.setState({items:[“Fly”]}); } componentDidMount(){ setTimeout(函数(){ 控制台日志(“2秒后”); this.setState({items:todos}); }.bind(this),2000年); } render(){ 返回(); } } ReactDOM.render(,document.getElementById(“app”);
是否要更改列表组件内的状态?@kumarm是的,这是我选择使用this.state.data时的意图。我将此值从props更改为state,以便在加载初始列表后更新状态。我的目的是创建一个项目列表,然后能够在通过拖放界面生成初始列表后对其重新排序。我仍然可以使用this.props方法来实现这种类型的功能吗?为了便于阅读,我省略了这一部分。谢谢@NightMarcher。我已经相应地更新了我的答案。@NightMarcher这解决了你的问题吗?如果是,请将此标记为答案。谢谢,谢谢!!直到现在我才有机会尝试一下。这正是我想要的。
let todos = ["Run","Swim","Skate"];

class MyList extends React.Component{
  componentWillMount() {
    console.log("Props are: ", this.props);
    this.setState({list: this.props.items});
  }

  componentWillReceiveProps(newProps) {
    console.log("Received Props are: ", newProps);
    this.setState({list: newProps.items});
  }

  render() {
    return (<ul>
            {this.state.list.map((todo) => <li>{todo}</li>)}
            </ul>);
  }
}

class App extends React.Component{
  constructor() {
      super();
      console.log("State is: ", this.state);
  }

  componentWillMount() {
    this.setState({items: ["Fly"]});
  }

  componentDidMount() {
    setTimeout(function(){
      console.log("After 2 secs");
      this.setState({items: todos});
    }.bind(this), 2000);
  }

  render() {
      return (<MyList items={this.state.items}/>);
  }
}


ReactDOM.render(<App/>, document.getElementById("app"));