Ad

Stop Relay: Query Renderer In Reloading Data For Certain SetStates

I'm currently following this and I did get it to work. But I would like to know if there is a way to stop the Query Render from reloading the data when calling this.setState(). Basically what I want is when I type into the textbox, I don't want to reload the data just yet but due to rendering issues, I need to set the state. I want the data to be reloaded ONLY when a button is clicked but the data will be based on the textbox value.

What I tried is separating the textbox value state from the actual variable passed to graphql, but it seems that regardless of variable change the Query will reload.

Here is the code FYR.

const query = graphql`
  query TestComponentQuery($accountId: Int) {
    viewer {
        userWithAccount(accountId: $accountId) {
            name
        }
    }
  }
`;

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

        this.state = {
            accountId:14,
            textboxValue: 14
        }
    }

    onChange (event){
      this.setState({textboxValue:event.target.value})
    }

    render () {
        return (

        <div>
          <input type="text" onChange={this.onChange.bind(this)}/>
            <QueryRenderer 
              environment={environment}
              query={query}
              variables={{
                  accountId: this.state.accountId,
              }}
              render={({ error, props }) => {
                  if (error) {
                    return (
                      <center>Error</center>
                    );
                  } else if (props) {
                    const { userWithAccount } = props.viewer;
                    console.log(userWithAccount)
                    return (
                      <ul>
                      {
                        userWithAccount.map(({name}) => (<li>{name}</li>))
                      }
                      </ul>
                    );
                  }

                  return (
                    <div>Loading</div>
                  );
                }}
            />
        </div>

        );
    }
}
Ad

Answer

Okay so my last answer didn't work as intended, so I thought I would create an entirely new example to demonstrate what I am talking about. Simply, the goal here is to have a child component within a parent component that only re-renders when it receives NEW props. Note, I have made use of the component lifecycle method shouldComponentUpdate() to prevent the Child component from re-rendering unless there is a change to the prop. Hope this helps with your problem.

Edit pedantic-sea-kis3i

class Child extends React.Component {
  shouldComponentUpdate(nextProps) {
    if (nextProps.id === this.props.id) {
      return false
    } else {
      return true
    }
  }
  componentDidUpdate() {
    console.log("Child component updated")
  }
  render() {
    return (
      <div>
        {`Current child ID prop: ${this.props.id}`}
      </div>
    )
  }
}

class Parent extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      id: 14,
      text: 15
    }
  }
  onChange = (event) => {
    this.setState({ text: event.target.value })
  }
  onClick = () => {
    this.setState({ id: this.state.text })
  }
  render() {
    return (
      <div>
        <input type='text' onChange={this.onChange} />
        <button onClick={this.onClick}>Change ID</button>
        <Child id={this.state.id} />
      </div>
    )
  }
}

function App() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}
Ad
source: stackoverflow.com
Ad