动态路由反应

时间:2020-09-11 01:25:49

标签: javascript reactjs react-router react-router-dom

回购:https://github.com/alxdelgado/reddit-clone

问题:该视图包含有关单个帖子的更多信息(包括对该帖子的评论)。

App.js

// import dependencies;
import React from 'react'; 
import { ThemeProvider } from 'styled-components';
import { Router, Route, Switch, Link, useParams, useRouteMatch } from 'react-router-dom';
import theme from '../theme';
import GlobalStyle from '../globalStyle';
import Home from '../components/Home/Home';
import Posts from '../components/Posts/Posts';
import Comment from '../components/Comments/Comment';
import Header from '../components/Header/Component';
import HeaderNavLink from '../components/Header/NavLink';

export default function App(props) {
    // theme provider adds "dark theme" to the app; WIP - not functional yet. 
    
    return (
        
            <ThemeProvider theme={theme(props.dark)}>
                    <>
                        <Header/>
                        <GlobalStyle />
                            <Switch>
                                <Route exact path='/' component={Home} />
                                <Route exact path='/posts' component={Posts} />
                                <Route name="comments" path='/comments' component={Comment} />
                            </Switch>
                    </> 
            </ThemeProvider>
        
    )
}

Posts.js

import React, { useState, useEffect, Suspense } from 'react'; 
import regeneratorRuntime from 'regenerator-runtime';
import styled from 'styled-components';

import { REDDIT_USER_AGENT, REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_REFRESH_TOKEN } from 'babel-dotenv';


// import components; 
import PostList from '../PostList/PostList';
import Loading from '../../assets/loader.gif';


// styled wrapper; 
const Wrapper = styled.div`
 
    align-items: center; 
    margin: 0 10vw; 

    @media (max-width: 1024px) {
        margin: 0 5vw; 
    }

    @media (max-width: 768px) {
        display: block;
        margin: 0; 
    }
`;

// fetch all "hot" posts; 
export default function Posts(props) {
    console.log("Posts -->", props);

    const [posts, setPosts] = useState([]);
    const [error, setError] = useState(false);
    const [loading, setLoading] = useState(false);

    useEffect(() => {
        // snoowrap api wrapper;
        // Docs: --> https://not-an-aardvark.github.io/snoowrap/index.html
        const snoowrap = require('snoowrap');
        // creating the snoowrap requester with OAuth credentials;
        const r = new snoowrap({
            userAgent: REDDIT_USER_AGENT,
            clientId: REDDIT_CLIENT_ID,
            clientSecret: REDDIT_CLIENT_SECRET, 
            refreshToken: REDDIT_REFRESH_TOKEN,
        });
        
        // fetch all "hot" posts; 
        // docs: https://github.com/not-an-aardvark/snoowrap
        // write the async function to fetch the data;
        
        
        const getRedditHot = async () => {
            if (error) {
                setError(true); 
            } else {
                setError(false);
                let response = await r.getHot('wec');
                const posts = response; 
                setPosts(posts);
                // console.log("getRedditHot -->", posts);
            }
        }   

        getRedditHot();
        // console.log("getRedditHot end of useEffect -->", posts); 
    }, []);

    console.log("getRedditHot outside useEffect -->", posts);

    return (
        <Suspense fallback={Loading}>
            <Wrapper>
                {posts.map((post, idx, ...otherPostProps) => {
                        return <PostList key={idx} props={post} {...otherPostProps} />
                })}
            </Wrapper>
        </Suspense>
    )
    
};

PostList.js

import React, { Suspense } from 'react';
import styled from 'styled-components'; 
import { Route, Switch, Link, useRouteMatch, useParams } from 'react-router-dom';

// import components; 
import ErrorBoundary from '../../util/ErrorBoundary';
import Loading from '../../assets/loader.gif';

// styled components;
const List = styled.ul`
    list-style: none; 
    border: 1px solid ${props => props.theme.border}; 
    border-radius: 5px;

    @media (max-width: 768px) {
        border-top: none; 
        border-left: none; 
        border-right: none; 
        border-radius: 0; 
    }
`;

const RedditTitle = styled.h1`
    text-decoration: none;
    font-size: 1rem;  

`; 

export default function PostList(props) {
    // console.log("PostList -->", props);

    // let { path, url } = useRouteMatch();

    // having trouble dynamically routing a link to each post 
    // that takes the user to a view of the individual posts, comments, likes, etc. 
    // Docs: --> https://github.com/ReactTraining/react-router/blob/v0.13.6/doc/03%20Components/Link.md#params

    return (
        <ErrorBoundary>
            <Suspense fallback={<h1>Loading...</h1>}>
                <List key={props.props.id}>
                    <h5>{props.props.subreddit_name_prefixed}</h5>
                    <RedditTitle>{props.props.title}</RedditTitle>
                    {/* <img src={props.props.thumbnail}/> */}
                    <li>
                        // my mental breakdown starts here;
                        <Link to={`/comments/${props.props.comments._uri}`}>More</Link>
                    </li>
                </List>
            </Suspense>
        </ErrorBoundary>
    )
};

问题在哪里-您如何通过包含该帖子的详细信息和评论的视图动态路由到另一个组件?因为我使用的是“ snoowrap API”,所以我必须点击另一个端点才能获取该帖子的评论,但是我无法通过匹配参数来匹配ID。

Comment.js(以防万一,您需要查看此内容)

import React, { useState, useEffect } from 'react';
import regeneratorRuntime from 'regenerator-runtime'; 
import styled from 'styled-components';

// import components; 
import CommentList from '../CommentList/CommentList';
import { sortData } from '../../util/sort';
// import env var;
import { REDDIT_USER_AGENT, REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET, REDDIT_REFRESH_TOKEN } from 'babel-dotenv';

// styled component;
const Wrapper = styled.div`
 
    align-items: center; 
    margin: 0 10vw; 

    @media (max-width: 1024px) {
        margin: 0 5vw; 
    }

    @media (max-width: 768px) {
        display: block;
        margin: 0; 
    }
`;

export default function Comment(props) {
    console.log("Comment component -->", props);

    const [comments, setComments] = useState([]);
    const [error, setError] = useState(false);
    const [loading, setLoading] = useState(false);

    useEffect(() => {
        // snoowrap api wrapper;
        // Docs: --> https://not-an-aardvark.github.io/snoowrap/index.html
        const snoowrap = require('snoowrap');
        // creating the snoowrap requester with OAuth credentials;
        const r = new snoowrap({
            userAgent: REDDIT_USER_AGENT,
            clientId: REDDIT_CLIENT_ID,
            clientSecret: REDDIT_CLIENT_SECRET, 
            refreshToken: REDDIT_REFRESH_TOKEN,
        });

        // fetch all "comments" of a subreddit post; 
        // docs: https://github.com/not-an-aardvark/snoowrap
        // write the async function to fetch the data;

        const getRedditComments = async () => {
            if (error) {
                setLoading(true);
                setError(true);
            } else {
                setError(false);
                setLoading(false);
                let response = await r.getSubreddit('wec').getNewComments();
                const sortedData = sortData(response); 
                const comments = sortedData; 
                setComments(comments); 
                // console.log("getRedditComments -->", comments);
            }

        }

        getRedditComments();
    }, []); 

    console.log(" getRedditCommments outside useEffect -->", comments);

    return (
        <Wrapper>
            <CommentList props={comments} />
        </Wrapper>
    )
};

1 个答案:

答案 0 :(得分:0)

这就是route params的用途。更新您的路线以设置参数:

<Route name="comments" path='/comments/:postid' component={Comment} />

链接到特定帖子的评论:

import { Link } from 'react-router-dom';

<Link to={`comments/${thePostId}`}>View Comments</Link>

然后在“评论”组件中use that来获取相应的评论:

import { useParams } from 'react-router-dom';

function Comment (props) {
  const {postid} = useParams();
  // do stuff with postid...
}