1

I have this routes:

App.js

...
<Switch>
    <Route exact path="/" component={Projects}/>

    <Route exact path="/projects/:folder?" component={Projects}/>
    <Route exact path="/projects/:folder/:id" component={Sketch}/>
    <Route exact path="/projects/:folder/:id/details" component={Details}/>

    <Route component={NoMatch}/>
</Switch>
...

I need to fetch data in the Projects page based on the folder param. I retrieve data correctly but it's not rendered. It renders the old list and the state changes. I tried like that:

Projects.js

render () {
    return (
        ...
        <Section>
            {this.state.projects}
        </Section>
        ...
    )
}

componentWillReceiveProps (newProps) {
    var params = newProps.match.params;
    this.setState({ folder: params.folder })
    this.loadProjects();
}

componentDidMount() {   
    this.setState({ folder: this.props.match.params.folder });
    this.loadProjects();
}

loadProjects () {
    const url = '/sketches' + (this.state.folder === 'sketches'? '':'/'+this.state.folder) + '/projects.json';
    axios.get(url).then((res) => {
        if (res.data !== null)
        {   
            const folder = this.state.folder === 'sketches' ? '': this.state.folder 
            this.setState({
                projects: <Grid list={res.data} folder={folder} key={"grid"}/>
            });
        }
    }).catch((ex) => {
        console.log(ex);
        this.setState({
            projects: <Redirect to="NoMatch"/>
        });
    })
}

I change params with a Link. I don't think is here the error, but I still put this code for you.
...I hope isn't here, because i passed all the time to check elsewhere.

render () {
    return (
        <Link to={this.state.url}>
            {this.props.item.name}
        </Link>
    )
}

componentDidMount () {
    var url = '/projects/' + this.props.item.name + '';

    if (!this.props.item.items) {
        url = '/projects/' + (this.props.folder || 'sketches') + '/' + this.props.item.name + '/details';
    }

    this.setState({ url })
}

I'm not using redux as you can see from this code.

4
  • Open the network tab, and then first check if the request is actually being made, and if yes, what status code and data is returned. Also why you want to pass empty string as props here const folder = this.state.folder === 'sketches' ? '': this.state.folder Commented Dec 16, 2017 at 20:37
  • First off, don't try to save the JSX component in your state. Save the information that you will pass to the JSX component in state. If there is no data to pass to the component on state, then conditionally render the Redirect. If there is, render the component and pass it the props you stored in the state. You're also going to want to add some condition in your componentWillReceiveProps because you're not going to want to do an api call on every render, only when the props change. Commented Dec 16, 2017 at 20:45
  • @Jay, it made two requests: one 404 /sketches/undefined/projects.json, the other 200 /sketches/specials/projects.json. I passed empty string because is the main folder in that case, otherwise is a subfolder inside the main folder. Commented Dec 17, 2017 at 14:15
  • @KyleRichardson, I tried like that and don't work {this.state.projects? <Grid list={this.state.projects} folder={this.state.folder} key={"grid"}/> : <Redirect to="NoMatch"/> } Commented Dec 18, 2017 at 12:46

2 Answers 2

2

Your problem may be to do with the fact that setState is generally asynchronous in behaviour. You can make use of the second callback parameter that setState has, which is a callback to invoke when the state has been actually updated:

componentWillReceiveProps (newProps) {
    var params = newProps.match.params;
    this.setState(
      { folder: params.folder },
      () => this.loadProjects());
}

componentDidMount() {   
    this.setState(
      { folder: this.props.match.params.folder },
      () => this.loadProjects());
}

If this does fix it, you may want to pass the info that loadProjects requires directly to it as parameter arguments.

Sign up to request clarification or add additional context in comments.

Comments

1

Thanks, I have used yours suggestions. Now it works, but I don't know why :D.
I changed this way and still wasn't working, but when I have modified some parent things I found it to work.

componentWillReceiveProps (newProps) {
    var params = newProps.match.params;

    if (params.folder !== this.state.folder)
        this.setState({ folder: params.folder || 'sketches' }, (folder) => this.loadProjects(this.state.folder));
}

componentDidMount() {   
    this.setState({ folder: this.props.match.params.folder || 'sketches' }, (folder) => this.loadProjects(this.state.folder));
}

I link my github project in case someone wants to take a look ;)
and maybe someone could tell me why it wouldn't work, but i don't claim anything. It works. For now, it's okay.

https://github.com/Darklod/p5-sketches-react

Comments

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.