2

Setup is es6 class:

export default class Gallery extends Component {
  addPhotos() {
    let data = [{}, {}, {}, {}, {}, {}]; // array of objects
    let dataChunks = chunk(data, 2); // returns array of two arrays [[{}, {}, {}],[{}, {}, {}]]

 // now here is where I am stuck. I want to:

  return dataChunk[0].map((photo) => (
    <PhotoComponent key={photo._id} photo={photo} />
  ));

 // wait 500ms and then add 3 more photos to the gallery (essentially throttling the loading)

  return dataChunk[1].map((photo) => (
    <PhotoComponent key={photo._id} photo={photo} />
  ));

Ideally, I am able to load 3 photos and then add the next 3 photos after 500ms.

As a bonus, having a loading component in between...

Thoughts?

What I have tried:

1) Using state to store the array. The problem seems to be rendering the array and changing it can cause a stack overflow problem.

2) Using a for loop with setTimeout... for some reason, the component props become undefined.

7
  • Run a setTimeout that changes the state with this.setState and you have some flag in the state that helps you determine what to render. Commented Mar 26, 2017 at 19:14
  • after 500 ms you want to replace the first 3 images or add new 3 images ? Commented Mar 26, 2017 at 19:21
  • @zerkms Can you give an example of what this would look like render and state and method Commented Mar 26, 2017 at 19:21
  • @MayankShukla I want to add 3 more images. Commented Mar 26, 2017 at 19:21
  • state would have numberOfPhotos property, with 3 set by default, and this.setState({ numberOfPhotos: 6 }); done on timer. render method would take the this.state.numberOfPhotos value and render the corresponding number of photos. And you don't need chunks at all. Commented Mar 26, 2017 at 19:24

2 Answers 2

3

Maintain a state variable that will check whether to render next part of array or not, and use timeout to change the status of that variable, it should work, Write it like this:

export default class Gallery extends Component {
    constructor(){
        super();
        this.state(
            renderNext: false,
            data: [{}, {}, {}, {}, {}, {}]
        )
    }

    _renderFisrtPart(){
        let data = this.state.data, arr = [];
        for(let i = 0; i < data.length/2; i++){
            arr.push(<PhotoComponent key={data[i]._id} photo={data[i]} />)
        }
        setTimeout(()=>{this.setState(renderNext: true)}, 500);
        return arr;
    }

    _renderSecondPart(){
        if(!this.state.renderNext) return;

        let data = this.state.data, arr = [];
        for(let i = data.length/2; i < data.length; i++){
            arr.push(<PhotoComponent key={data[i]._id} photo={data[i]} />)
        }

        return arr;
    }

    render(){
        return(
            <div>
                {this._renderFisrtPart()}
                {this._renderSecondPart()}
            </div>
        )
    }
}
Sign up to request clarification or add additional context in comments.

Comments

1

This would be my approach, using setTimeout inside the componentDidMount method. You could also wrap it inside a Promise and chain addData down with then.

export default class Gallery extends Component {
  constructor(props) {
    super(props);

    this.addData = this.addData.bind(this);

    this.state = { data: [] };
  }

  componentDidMount() {
    // Don't know if you're getting your data via props
    const data = this.props.data || [{}, {}, {}, {}, {}, {}];
    const chunks = chunk(data, 2);

    this.addData(chunks[0])();
    setTimeout(this.addData(chunks[1]), 500);
  }

  addData(data) {
    return () => this.setState({
      data: [
        ...this.state.data,
        ...data,
      ],
    });
  }

  render() {
    return this.state.data.map(photo => <PhotoComponent key={photo._id} photo={photo} />);
  }
}

8 Comments

i think it should be data: [ ...this.state.data, ...data ], ???
Yes, fixed it. Thank you! :)
awesome dude, really nice structure +1 :)
@OleBläsing Okay, I decided to try this first, as it was closest to my original. So, the data is not ready by componentDidMount() hook, just consoles to an empty array. I had to move the call into componentDidUpdate() but now the data returns as an array of objects. Problem now is the stack overflow created by the hook being called, state being changed, and then hook being called etc... but I think this can work if setup a bit different... ideas?
You do not need to use componentDidUpdate. The state should be filled, after the componentDidMount method executes. Why do you need the filled state before? You could set your first chunk in the constructor, but there would be no benefit, if you not use it.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.