0

I am building a forum and I want to make it where: Once you click on the title, it displays a page (which I already created) that displays the post title and then the post body. I used MUI to build the page as well. However, the Axios call fails when I call the backend and appending the "this.state.props." to the end.

My "All Questions" page code in which the user which select which post to open:

    export default class DisplayPosts extends Component { 
       constructor(props) {
            super(props);
            this.state = {
                posts: [],
                selectedPostId: null,
            };
       }
       componentDidMount (){ 
        axios.get('http://localhost:6006/api/v1/posts')
              .then(res=> { 
                const posts = [];
                for (let key in res.data.data) {
                    posts.push({...res.data.data[key], id: key});
                }
                this.setState({
                    posts: posts,
                  })
                  console.log('Pulling From::  ', res.data.data)
                 })
              .catch(err => console.log('err::  ', err)
              )
        } 

        onPostClickHandler = (_id) => {
            this.setState({
                selectedPostId: _id,
            })
            console.log(_id)
        } 

render() { 
    const posts = this.state.posts.map((post) => {
        return <Posts 
                key ={post._id} 
                post={post}
                postclicked = {this.onPostClickHandler.bind(
                    this,
                    post._id, 
                )} />;
    })
    return (
        <Box component="main" 
        sx={{ flexGrow: 1, p: 3, marginLeft: "300px",marginTop:"-40px" }}>
            <Toolbar />
            <Stack spacing={2}> 
                <Typography> 
                   <h1> All Questions </h1> 
                </Typography>
                <Button
                sx={{}}
                variant = 'outlined'
                size = 'medium'
                color = 'secondary'>
                    Ask New Question
                </Button>
                <Divider /> 
                    <div> 
                    {posts}
                    </div> 
            </Stack>
            {this.state.selectedPostId && ( 
                <ViewPosts _id={this.state.selectedPostId} />
            )}
        </Box> 
    )
}
}

My "View Posts" page, the page where the user will see the information of the post they just clicked

    export default class ViewPosts extends Component {  
    constructor(props){
        super(props);
        this.state = { 
            post: null,
        }
    }
componentDidMount (){ 
        axios.get(`http://localhost:6006/api/v1/posts/${this.props._id}`)
              .then(res=> { 
                this.setState({
                    posts: {...res.data.data, _id: this.props._id}
                  })
                  console.log('Pulling From::  ', res.data.data)
                 })
              .catch(err => console.log('err::  ', err)
              )
        } 
render() { 
    return (
        <div> 
        <><Box component="main"
            sx={{ flexGrow: 1, p: 3, marginLeft: "300px", marginTop: "-40px" }}>
            <Toolbar />
            <Typography>
                <h1>{this.state.post.title} </h1>
                <p>Added: Today ..........Viewed: -- times </p>
            </Typography>
            <Divider />
            <Stack direction='row' spacing={3}>
                <Stack
                    direction="column"
                    spacing={2}>
                    <IconButton>
                        <KeyboardDoubleArrowUpIcon color='primary' />
                    </IconButton>
                    <IconButton sx={{ marginTop: '2px' }}>
                        <KeyboardDoubleArrowDownIcon color='primary' />
                    </IconButton>
                </Stack>
                <Typography>
                    <h6>  </h6>
                </Typography>
                <Typography>
                    <p>
                       {this.state.post.body} 
                    </p>
                </Typography>
            </Stack>
            <Divider />
            <TextField
                sx={{ marginTop: "20px", marginLeft: "0px", width: '950px' }}
                id="filled-multiline-static"
                label="Enter Answer Here..."
                multiline
                rows={8}
                variant="filled" />

            <Button
                sx={{ marginTop: "15px" }}
                variant='contained'
                size='large'
                color='primary'
            >
                Post Your Answer
            </Button>
        </Box>

        </>
    </div>
    )
    } 
}

  • On the View Posts page you use set post in the state in the constructor and then i the axios result handling you have posts, these should not differ – P-A Oct 25 '22 at 09:02

1 Answers1

0

From my understanding, componentDidMount is called after the component is mounted.

And by that, I mean the axios call will happen immediately, while the DOM content will take more time to load.

So, chances are, what happens is that you're not going to see anything, even if the axios call is finished and the state of the ViewPost is no longer null.

What you may wanna do now is to create a logic that prevents the DOM of the post from being displayed until the state is populated.

Like, for example...

render() { 
    return this.state.post && (
        <div> 
        <><Box component="main"
            sx={{ flexGrow: 1, p: 3, marginLeft: "300px", marginTop: "-40px" }}>
            <Toolbar />
            <Typography>
                <h1>{this.state.post.title} </h1>
                <p>Added: Today ..........Viewed: -- times </p>
            </Typography>
            <Divider />
            <Stack direction='row' spacing={3}>
                <Stack
                    direction="column"
                    spacing={2}>
                    <IconButton>
                        <KeyboardDoubleArrowUpIcon color='primary' />
                    </IconButton>
                    <IconButton sx={{ marginTop: '2px' }}>
                        <KeyboardDoubleArrowDownIcon color='primary' />
                    </IconButton>
                </Stack>
                <Typography>
                    <h6>  </h6>
                </Typography>
                <Typography>
                    <p>
                       {this.state.post.body} 
                    </p>
                </Typography>
            </Stack>
            <Divider />
            <TextField
                sx={{ marginTop: "20px", marginLeft: "0px", width: '950px' }}
                id="filled-multiline-static"
                label="Enter Answer Here..."
                multiline
                rows={8}
                variant="filled" />

            <Button
                sx={{ marginTop: "15px" }}
                variant='contained'
                size='large'
                color='primary'
            >
                Post Your Answer
            </Button>
        </Box>

        </>
    </div>
    )
    } 
}

Dennis Quan
  • 149
  • 1
  • 5
  • Thank you for answering! I tried this and it still didn't work. I think it has something to do with my Axios call, since I am getting a 404. However, I know the url is correct and if I hard code the post id into the axios call, it will return something. Is there a problem with my syntax or how I am passing the props into the axios call url? – airemike Oct 25 '22 at 13:32
  • Have you found any clues to that yet ? Because I don't see anything wrong with your syntax. – Dennis Quan Oct 26 '22 at 01:54