4

Suppose you have a comment, and you want to refer to a comment via anchor text, so something like this for example.

This is a permalink to a comment on a post, which demonstrates the objective.

https://stackoverflow.com/a/31079244/7174241

enter image description here

How would you go about setting permalinks for each comment in a list of comments, so you can refer to any comments by a permalink ?

Not sure if this can be done in front end, or this is more of an orm database thing, where setting a unique permalink as per table structure would be more ideal.

So for example you have a comment list component like this

CommentList.js

<Fragment>
  {/* filter based on first comment  */}
  {filterComments.map((comment, i) => (
    <div key={i} ref={ref} className="comment">
      <CommentItem comment={comment} />
    </div>
  ))}
</Fragment>;

CommentItem.js

<Fragment>

  <div id="permalink id goes here ?">
    <Link to="/393829fjf"> </Link> ?? // should a link go here
    <p>{comment.body}</p>
  </div>
</Fragment>;

Similar question but no helpful solution.

Div anchor tag in a react component

BARNOWL
  • 3,326
  • 10
  • 44
  • 80

1 Answers1

3

How Stackoverflow does it

Doing a quick curl -v https://stackoverflow.com/a/31079244/7174241 in my command line shows that StackOverflow is using the backend to lookup the answer, generate the link, and then redirect the browser to that link:

> GET /a/31079244/7174241 HTTP/2
> Host: stackoverflow.com
> User-Agent: curl/7.64.1
> Accept: */*
> 
< HTTP/2 302 
< cache-control: private
< location: /questions/31079081/programmatically-navigate-using-react-router/31079244#31079244

How could this translate to the front end

Well, if we have an API that we can use to fetch the "answer" in question, then we can build up the path string with generatePath().

Lets say our permalink is mysite.com/a/{answerId}

and our answer link is mysite.com/questions/{questionId}

Next, we will need to create a top level route entry:

<Route path="/questions/{questionId}" component={SomeQuestionPage} />
<Route path="/a/{answerId}" component={SomeAnswerRedirectPage} />

Inside of SomeAnswerRedirectPage we would want to make a call to the back end to fetch the answer (which should probably also contain the question ID that it belongs to)

Then, we can redirect using <Redirect />/useHistory and generatePath:

function SomeAnswerRedirectPage() {
  const history = useHistory();
  const { answerId } = useParams();

  useEffect(() => {
    someApiCall.getAnswerData(answerId)
      .then(response => {
        const { questionId } = response.data.answer;
        const path = generatePath('/questions/{questionId}', {
          questionId
        });

        history.push(`${path}#${answerId}`);
          
      })
  }, []);

  return null;
}

Finally, inside of our SomeQuestionPage make sure we have an anchor tag surrounding the answer we want to scroll to

function SomeQuestionPage() {
  return (
    <div>
      {question.title}
      <div>
        {question.answers.map(answer => (
          <a href={`#${answer.id}`} key={answer.id}>
            <SomeAnswerDisplay answer={answer} />
          </a>
        ))}
      </div>
    </div>
  );
}
Derek Pollard
  • 6,953
  • 6
  • 39
  • 59
  • Thank you for this explanation, will go through these steps. And see what i come with. Thanks again. – BARNOWL Aug 28 '20 at 16:28
  • @BARNOWL - no problem! Let me know how it goes! – Derek Pollard Aug 28 '20 at 16:29
  • hmm i tried a similar approach, how would you refer to these items with a hash using react router, and possible add the scrollIntoView effect for any comment item. React router ignores the hash. for example if i do `#comment34020` it just ignores it. I have something like this `` – BARNOWL Aug 28 '20 at 21:41
  • You wouldn't add the hash into the route path, React Router wont act on that. What will act on that, however is the browser once you've redirected. Also, make sure the answer href has a `#` at the beginning. Forgot to add that above; edited accordingly – Derek Pollard Aug 28 '20 at 22:05