递归数据和组件,稍后提取错误

Gre*_*ber 4 reactjs graphql relayjs

首先关闭我的graphql数据模型:

type Human {
  id: !String,
  name: !String,
  children: [Human]
}
Run Code Online (Sandbox Code Playgroud)

我正在使用的唯一路由(中继路由配置):

class extends Relay.Route {
  static queries = {
    human: () => Relay.QL`query RootQuery { viewer }`
  };
  static routeName = 'AppHomeRoute';
}
Run Code Online (Sandbox Code Playgroud)

列表组件:

class HumanList extends Component {
  render() {
    let {children} = this.props.human;

    let subListsHTML = human ? children.map(child => (
      <HumanListItem key={child.id} human={child}/>
    )) : '';

    return <ul>{subListsHTML}</ul>;
  }
}

export default Relay.createContainer(HumanList, {
  fragments: {
    human: () =>  Relay.QL`
      fragment on Human {
        children {
          id,
          ${HumanListItem.getFragment('human')}
        }
      }
    `
  }
});
Run Code Online (Sandbox Code Playgroud)

列表项组件:

class HumanListItem extends Component {
  state = {expanded: false};

  render() {
    let {human} = this.props;

    let sublistHTML = '';
    if (this.state.expanded) {
      sublistHTML = <ul><HumanList human={human}/></ul>;
    }

    return (
      <li>
        <div onClick={this.onClickHead.bind(this)}>{human.name}</div>
        {sublistHTML}
      </li>
    );
  }

  onClickHead() {
    this.props.relay.setVariables({expanded: true});
    this.setState({expanded: true});
  }

}

HumanListItem.defaultProps = {viewer: {}};

export default Relay.createContainer(HumanListItem, {

  initialVariables: {
    expanded: false
  },

  fragments: {
    human: (variables) =>  Relay.QL`
      fragment on Human {
        name,
        ${HumanList.getFragment('human').if(variables.expanded)}
      }
    `
  }

});
Run Code Online (Sandbox Code Playgroud)

哪个运行正常的根列表.但是,只要我单击ListItem并将其展开,我就会收到以下错误:

Warning: RelayContainer: Expected prop 'human' supplied 'HumanList' to be data fetched by Relay. This is likely an error unless you are purposely passing in mock data that conforms to the shape of this component's fragment.

我无法理解它,因为我传递的数据不是模拟的,而是直接由Relay获取,如HumanList comp中所示.

Joe*_*ona 10

该错误表示<HumanList>在数据准备好之前正在呈现.

class HumanListItem extends Component {
  onClickHead() {
    this.props.relay.setVariables({expanded: true});
    this.setState({expanded: true});  // <-- this causes the component to re-render before data is ready
  }
Run Code Online (Sandbox Code Playgroud)

您可以改为查看变量的当前值,而不是使用状态:

class HumanListItem extends Component {
  // no need for `state.expanded`

  render() {
    let {human} = this.props;

    let sublistHTML = '';
    if (this.props.relay.variables.expanded) {
      // `variables` are the *currently fetched* data
      // if `variables.expanded` is true, expanded data is fetched
      sublistHTML = <ul><HumanList human={human}/></ul>;
    }

    return (
      <li>
        <div onClick={this.onClickHead.bind(this)}>{human.name}</div>
        {sublistHTML}
      </li>
    );
  }

  onClickHead() {
    this.props.relay.setVariables({expanded: true});
    // no need for `setState()`
  }

}

HumanListItem.defaultProps = {viewer: {}};

export default Relay.createContainer(HumanListItem, {

  initialVariables: {
    expanded: false
  },

  fragments: {
    human: (variables) =>  Relay.QL`
      fragment on Human {
        name,
        ${HumanList.getFragment('human').if(variables.expanded)}
      }
    `
  }

});
Run Code Online (Sandbox Code Playgroud)