Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript React-回调中未使用props表达式集重新排序的子组件数组_Javascript_Reactjs_Socket.io - Fatal编程技术网

Javascript React-回调中未使用props表达式集重新排序的子组件数组

Javascript React-回调中未使用props表达式集重新排序的子组件数组,javascript,reactjs,socket.io,Javascript,Reactjs,Socket.io,我知道这个问题的措辞有点含糊不清,所以我将进一步阐述。这是我的一个个人项目,我学习了一些基础知识,并熟悉socket.io 我有一个可折叠列表组件和一个NestedList组件,它呈现一个可折叠列表组件数组 NestedList有一个在组件的componentWillMount中设置的事件处理程序。事件发生在通过socket.io从我的服务器到达菜单时。当菜单到达时,将向数组中添加一个新的可折叠列表,并更改状态以触发重新加载。事件由通过componentDidMount(获取菜单)发出的初始so

我知道这个问题的措辞有点含糊不清,所以我将进一步阐述。这是我的一个个人项目,我学习了一些基础知识,并熟悉socket.io

我有一个可折叠列表组件和一个NestedList组件,它呈现一个可折叠列表组件数组

NestedList有一个在组件的componentWillMount中设置的事件处理程序。事件发生在通过socket.io从我的服务器到达菜单时。当菜单到达时,将向数组中添加一个新的可折叠列表,并更改状态以触发重新加载。事件由通过componentDidMount(获取菜单)发出的初始socket.io事件触发

可折叠列表通过其onclick进行折叠/解压,onclick使用从NestedList通过props传递的toggleVisiblity方法,NestedList的状态决定其子可折叠列表组件是否打开

问题:可折叠列表道具(来自NestedList的状态)不会随着所述NestedList状态的改变而改变。我已经检查了调试器中的属性,我已经被困了好几天了。换句话说,可折叠列表元素出现在浏览器窗口中,但单击它只会更改嵌套列表的状态,可折叠列表的支柱不会更改,因此不会出现/消失。我认为这与在socket.io回调中创建与“this”绑定的可折叠列表有关,因为可折叠列表的“collapsed”属性依赖于此。state[restaurantId]。collapsed。来源如下,如果不清楚,我可以补充更多的解释

class CollapsibleList extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    return (
      <List>
        <ListItem
          button
          onClick={() => {
            this.props.collapseEventHandler(this.props.restaurantId);
          }}
        >
          <ListItemText primary="Collapse me!" />
        </ListItem>
        <ListItem>
          <Collapse in={!this.props.collapsed} timeout="auto" unmountOnExit>
            <ListItemText primary="Hello World!" />
          </Collapse>
        </ListItem>
      </List>
    );
  }
}

class NestedList extends React.Component {
  constructor(props) {
    super(props);
    //let menuData = props.menuData.map()
    this.toggleVisiblity = this.toggleVisiblity.bind(this);
    this.arrayOfMenus = [];
  }

  componentWillMount() {
    socket.on(
      "menu-arrived",
      function(menuJson) {
        if (menuJson.response.menu.menus.items) {
          let restaurantId = menuJson.restaurant_id;
          //let menuId = menuJson.response.menu.menus.items[0].menuId;
          this.arrayOfMenus.push(
            <CollapsibleList
              collapsed={this.state[restaurantId].collapsed}
              collapseEventHandler={this.toggleVisiblity}
              restaurantId={restaurantId}
              key={restaurantId}
            />
          );
          this.setState(function(prevState, props) {
            return {
              [restaurantId]: {
                collapsed: prevState[restaurantId].collapsed,
                updated: true
              }
            };
          });
        }
      }.bind(this)
    );
  }

  componentDidMount() {
    getNearbyRestaurantRawData().then(
      function(rawData) {
        let restaurantIds = parseOutVenueIds(rawData);
        let menusOpen = {};
        for (let i = 0; i < restaurantIds.length; i++) {
          menusOpen[restaurantIds[i]] = {
            collapsed: true
          };
        }
        this.setState(menusOpen, () => {
          socket.emit("get-menus", {
            ids: restaurantIds
          });
        });
      }.bind(this)
    );
  }

  toggleVisiblity(restaurantId) {
    this.setState(function(prevState, props) {
      let newState = Object.assign({}, prevState);
      newState[restaurantId].collapsed = !prevState[restaurantId].collapsed;
      return newState;
    });
  }

  render() {
    return (
      <List>
        <React.Fragment>
          <CssBaseline>{this.arrayOfMenus}</CssBaseline>
        </React.Fragment>
      </List>
    );
  }
}
类可折叠列表扩展了React.Component{
建造师(道具){
超级(道具);
}
render(){
返回(
{
this.props.collapseEventHandler(this.props.restaurantId);
}}
>
);
}
}
类NestedList扩展了React.Component{
建造师(道具){
超级(道具);
//让menuData=props.menuData.map()
this.togglevisibility=this.togglevisibility.bind(this);
this.arrayOfMenus=[];
}
组件willmount(){
插座(
“菜单到了”,
函数(menuJson){
if(menuJson.response.menu.menus.items){
让restaurantId=menuJson.restaurant\u id;
//让menuId=menuJson.response.menu.menu.items[0].menuId;
这是arrayOfMenus推(
);
this.setState(函数(prevState、props){
返回{
[餐厅]:{
折叠:prevState[餐厅]。已折叠,
更新:正确
}
};
});
}
}.绑定(此)
);
}
componentDidMount(){
getNearbyRestaurantRawData()。然后(
函数(原始数据){
let restaurantIds=parseOutVenueIds(原始数据);
让menusOpen={};
for(设i=0;i{
发出(“获取菜单”{
ID:餐厅
});
});
}.绑定(此)
);
}
切换可视性(餐厅){
this.setState(函数(prevState、props){
让newState=Object.assign({},prevState);
newState[restaurantId]。已折叠=!prevState[restaurantId]。已折叠;
返回新闻状态;
});
}
render(){
返回(
{this.arrayOfMenus}
);
}
}

您正在将
可折叠列表
React元素推送到实例上的数组中,这意味着当状态或道具更改时,将不会创建新的React元素并从渲染方法返回

您应该始终从呈现方法中的状态和道具派生UI

示例

class NestedList extends React.Component {
  state = { restaurantIds: [] };

  componentWillMount() {
    socket.on("menu-arrived", menuJson => {
      if (menuJson.response.menu.menus.items) {
        let restaurantId = menuJson.restaurant_id;
        this.setState(prevState => {
          return {
            restaurantIds: [...prevState.restaurantIds, restaurantId],
            [restaurantId]: {
              collapsed: prevState[restaurantId].collapsed,
              updated: true
            }
          };
        });
      }
    });
  }

  // ...

  render() {
    return (
      <List>
        <React.Fragment>
          <CssBaseline>
            {this.state.restaurantIds.map(restaurantId => (
              <CollapsibleList
                collapsed={this.state[restaurantId].collapsed}
                collapseEventHandler={this.toggleVisiblity}
                restaurantId={restaurantId}
                key={restaurantId}
              />
            ))}
          </CssBaseline>
        </React.Fragment>
      </List>
    );
  }
}
类嵌套列表扩展了React.Component{
状态={restaurantIds:[]};
组件willmount(){
on(“菜单到达”,menuJson=>{
if(menuJson.response.menu.menus.items){
让restaurantId=menuJson.restaurant\u id;
this.setState(prevState=>{
返回{
restaurantIds:[…prevState.restaurantIds,restaurantId],
[餐厅]:{
折叠:prevState[餐厅]。已折叠,
更新:正确
}
};
});
}
});
}
// ...
render(){
返回(
{this.state.restaurantIds.map(restaurantId=>(
))}
);
}
}

不要将JSX推到
this.arrayOfMenus
,而是应该将数组中的所有
restaurantId
保持为状态,并从render方法中的状态派生JSX。对,这很有意义,因为我可以避免任何“this.state”问题,我将尝试这样做。考虑到“this”绑定是准确的,我真的很好奇为什么道具没有随着重播器的出现而改变。你正在将
推到一个数组中,所以当道具或状态改变时,你永远不会为
可折叠列表创建新的React元素。您应该总是从render方法中的状态和道具派生JSX。我明白了,所以我以前的理解是有缺陷的。如果jsx不是在render方法中派生的,react无法直接替换/修改它?。如果只创建元素并将它们存储在数组中,则永远不会创建新元素。我知道我以前的错误所在。render所能看到的只是显示现有组件数组的指令。状态的所有变化意味着对渲染的另一次调用。是的!我感谢你的及时帮助。我希望我能提高投票率,但看起来我需要更多的声誉来进行任何访问