使用Reddit的API查找Pokemon交易

发布于:2021-02-19 00:02:20

0

243

0

初学者 100天代码 Reddit Pokemon react

  

从字面上看,自启动React以来,我所有的项目都是基于Pokemon或使用Pokemon艺术。她可能喜欢神奇宝贝吗?

通过编码我发现了一件奇怪的事情,那就是对数据进行排序很有趣?碰巧pokemon包含了许多有趣的数据小道消息,可以进行排序,并与其他内容进行匹配。所以,我再一次使用了一个API和一些pokemon,但是这次我们使用的是Reddit的API。

目标

  • 从各个子Reddits获取数据

  • 了解Reddit的api术语是什么

  • 显示pokemon在标题和帖子中提到的内容

  • 通过pokemon的交易进行搜索

我们都得到了吗?让我们看看发生了什么。

Reddit

Reddit是互联网上的一个地方,由用户运行的subreddit组成。每样东西都有一个子项,事实上,可能每样东西都有不同的规则。对于这个项目,我想subreddits是专门用于交易的口袋妖怪,是经常更新,并使用类似的预修复。对于我选择的三个子项,它们在大多数查找中都使用LF(寻找)和FT(交易)。现在我们继续讨论如何使用reddit的api。我们来分析一下我的第一个电话。

axios.get(`https://www.reddit.com/r/pokemontrades/search.json?q=LF&q=FT&limit=30&restrict_sr=1&sort=new`)

简单部分:

`https://www.reddit.com/r/pokemontrades/search.json?`

我们通过reddit,然后指定子reddit,然后启动一个搜索,得到一个包含所有信息的.json文件。

  `/search.json?q=LF&q=FT`

我们问两个搜索问题。里面有LF吗?它包含FT吗?如果有那么好的话。我们也无法查询和获取所有帖子,但如果有不符合格式的问题或mod更新,我们希望将其剔除。

`limit=30&restrict_sr=1`

有一个更严格的限制是100个,但我真的不希望人们通过300个条目,所以我们只会拉30个subreddit,共90个上市。限制的好处是,这都是一个api调用!下一部分,我们将搜索限制到我们定义的特定子项。为什么?我不知道。如果您不这样做,它会在所有子项中显示出来,这是我们真正不需要的。

`&sort=new`

如果你熟悉reddit,这个很简单。Reddit有各种模式可以按时间的顶端排序,按当前时间的热点排序,然后按最新的排序,等等。我们想要最新的交易,所以我们想要的不是相关性,而是最新的。

这些数据是什么?

很多。不幸的是,这还不够。我们可以遍历数据,进入被请求的30个孩子并获得大量数据!我们可以获取帖子标题,正文,风格,mod操作和...

不是日期?

创建字段的日期是发出请求的日期。正如我刚刚要求的那样,所以这是创建日期或utc。根据我的研究,没有为api提供可用的时间戳记。这给我的计划带来了麻烦。

原计划

我打算使用查询来查找pokemon相关的条目!因此,我们不使用常规查询,而是使用以下内容:

axios.get(`https://www.reddit.com/r/pokemontrades/search.json?q=Vulpix&limit=30&restrict_sr=1&sort=new`)

这确实有效。它将收集所有能找到的关于vulpix的帖子,最多30篇。不过,有些已经有几个月大了。虽然我有过简单地提供数据的实践,但作为一种更静态的资源,我希望它至少有点有用。当然,我可以搜索特定的pokemon,但是没有一个截止日期的方法,它只是白噪音,使它看起来更强大,然后有用。

新计划

缓存数据!我们的内容一旦是动态的,就不会像本地浏览器中的缓存那样,而是接受我们最初的调用并使用这些数据。因此,与其找一些关于pokemon的老东西,不如看看最新的90条帖子中提到了哪个pokemon。

return general.map((listing, i) => {         let post = listing.data;         let pkmnMentioned = this.getPKMNMentioned(post);         if (pkmnMentioned.includes(pokemon, i)) {           return <Entry             key={post.title + i}             subName={post.subreddit_name_prefixed}             title={post.title}             url={post.url}             text={post.selftext}             searchPokemon={this.state.searchPokemon}             setSpecificAndPokemon={this.setSpecificAndPokemon}           />;         } else {           return "";         }       });

 

关键是要使用一个唯一的标识符,这是原来的标题本身不是,因为在测试期间有人双重张贴,它真的搞砸了我的渲染。吸取的教训。searchPokemon是一个状态变量,它保存了我们当前正在搜索的pokemon,因此我们可以向下传递它并突出显示我们正在搜索的精灵。如果我们正在搜索一个特定的口袋妖怪或者没有,我们也会传递设置这个状态和布尔值的能力。

我最初让Entry组件来确定提到了哪个pokemon,但是就像React一样,您通常会找到一个理由来提升处理级别。上面提到的getpkmn只是通过pokemonArray(一个包含所有pokemon的数组,说真的,它很长)搜索标题和自我文本(body),看看pokemon是否出现在它的数据中。Search返回数据所在位置的数字,如果数据不在其中则返回-1,因此我们只需查看该数字是否大于-1即可推送到pokmemon提到的数组。由于大部分提到都是在身体里进行的,所以我决定先这样做,如果身体没有返回特定的口袋妖怪,它会在标题中搜索口袋妖怪,这样我们就不会加倍并掩盖我们的基础。

{this.state.general[89] ? listings : "Loading..."}

作为一个简短的说明,因为我们知道我们只搜索了90个条目,所以我们可以用它来确定我们是否完成了加载我们所做的三个调用。我喜欢这个api。一张纸条一张纸条,我其实不写此.state.value对于所有的事情,我只是在文章代码中有它,这样你就可以看到发生了什么。我应该做一个更复杂的加载动画,但它似乎太琐碎相比,它实际上需要多长时间加载。

条目组件

因为我们把pokemon的搜索从我们的条目中删除了(或者更确切地说,我在写这篇文章的时候忘了把它删除,谢谢您查看代码!)是相当稀疏的。最重要的一点是,我们的图像名称摆脱了特殊的字符和斩首他们,所以我们必须做一点正则表达式的魔力,使之工作。一点额外的魔力,将自我文本中的内容变回一个

import React from 'react'; import Sprite from './Sprite'; export default function Entry(props) {   props.pkmnMentioned.forEach(pokemon => {     let spriteName = pokemon       .replace(/s+/g, '-')       .replace(/[.,':s]/g, "")       .replace(/♀/g, "-f")       .replace(/♂/g, "-m")       .toLowerCase();     spritesMentioned.push(       <Sprite         key={pokemon}         fullName={pokemon}         name={spriteName}         isSearched={pokemon === props.searchPokemon}         setSpecificAndPokemon={props.setSpecificAndPokemon}       />     );   })   return (     <div className="entry">       <div className="subname">{props.subName}</div>       <a         href={props.url}         target="_blank"         rel="noopener noreferrer"         className="title"       >         {props.title.replace(/(&amp;)/g, "&")}       </a>       <div className="sprites-container">         <h3>Pokemon Mentioned:</h3>         <div className="sprites">           {spritesMentioned.length ? spritesMentioned : "None"}         </div>       </div>     </div>   ); }

rel=“noopener或noreferrer”

让我们花点时间来确认我所做的事情,因为如果我不这样做,React会对我大喊大叫。如果我在目标空白处打开,React会告诉我,在没有rel=“noopener noreferrer”的情况下这样做会有安全风险。让我用谷歌搜索一下,也许我们都会学到一些新东西。

我们链接到的页面通过开窗器“对象”。因此,可以在看起来合法的链接上插入javascript来重定向到一个不好的站点。这篇文章中最有趣的部分是,谷歌只是接受了这一点,认为这是“当前网页浏览器设计的固有特点,任何一个网站都无法有效缓解”。

精灵组件

比条目更小的是Sprite组件。只需将它插入到条目中,而不是它自己的组件是可能的,但我觉得Sprite显示是一项非常重要的工作,足以保证它自己的组件。

import React from 'react'; export default function Sprite(props) {   return (     <div       className={`circle ${props.isSearched ? 'highlight' : ""}`}       key={props.name}       onClick={() => props.setSpecificAndPokemon(true, props.fullName)}     >       <img         src={`${process.env.PUBLIC_URL}/regular/${props.name}.png`}         alt={props.fullName}         title={props.fullName}       />     </div>   ); }

在完整的版本中,你可以通过下拉菜单选择要搜索的pokemon,但是我也希望能够点击精灵来搜索更多的pokemon。我们保留了alt文本的全名,title(如果你忘记了pokemon的名字,但是知道它是什么样子的话,你可以把鼠标悬停在上面),最重要的是,当我们改变搜索条件时,我们使用pokemon的正确名称。circle类和highlight类为我们提供了我在它们周围放置的圆圈的外观,以及pokemon是否是当前正在搜索的那个。


 circle {       background-color: rgba(white, 0.3);       border-radius: 50%;       margin: 5px;       cursor: pointer;     }     .highlight {       background-color: rgba($link-color, 1);     }

小额回报vs膨胀

我开始做一件事,我不敢肯定这件事是否好?我希望在我的呈现中有小的返回语句。

return (       <div id="app">         {this.state.specific ? lookSpecific : all}         {searchAll}         <div id="listing-container">           {this.state.general[89] ? listings : "Loading..."}         </div>       </div>

那很好。但是,它前面有这样一条:

const { general, specific, searchPokemon } = this.state;     let listings = this.listings(specific, searchPokemon) || 0;     const all = <header>Searching last 30 results of 3 subreddits...</header>;     const lookSpecific = <header>Searching last 90 results for trades containing {searchPokemon}...</header>;     let cantFind = listings.length ? "" : "Couldn't find any trades!"     const lookups = pokemonArray.map((pokemon, i) => {       return (         <option           key={pokemon + ` option`}           value={pokemon}         >           {`${pokemon} #${i + 1}`}         </option>       );     });     const searchAll =       <select         onChange={e => this.setSpecificAndPokemon(true, e.target.value)}       >         <option           key='none'           value={null}           onClick={() => this.setSpecificAndPokemon(false, null)}         >           None         </option>         {lookups}       </select>

另一种方法是只在return语句中定义它,但是你会得到这样的结果:在我看来这很难理解。

const { general, specific, searchPokemon } = this.state;     let listings = this.listings(specific, searchPokemon) || 0;     return (       <div id="app">         {this.state.specific ?           <header>Searching last 90 results for trades containing {searchPokemon}...</header>           : <header>Searching last 30 results of 3 subreddits...</header>}         <select           onChange={e => this.setSpecificAndPokemon(true, e.target.value)}         >           <option             key='none'             value={null}             onClick={() => this.setSpecificAndPokemon(false, null)}           >             None     </option>           {pokemonArray.map((pokemon, i) => {             return (               <option                 key={pokemon + ` option`}                 value={pokemon}               >                 {`${pokemon} #${i + 1}`}               </option>             )           })}         </select>         <div id="listing-container">           {this.state.general[89] ? this.listings(specific, searchPokemon) || 0 : "Loading..."}         </div>       </div >     );   }

这样把它们分开是不对的,还是render语句应该按照其中的内容的顺序来读?对if语句使用立即返回函数非常难看,但使用真正长的三元运算符也是难看的。

{(() => {      if (ugly) {        return <div> Man this is {`ugly`}.. </div>      } else {        return <div> But it's more informative? </div>      }    })()}

最后的想法

我觉得我已经做了三次同一个项目的变化,但每次我都学到了一些东西。至少对我来说,想出我力所能及的好主意是困难的。我对一些游戏有一些想法要感谢朋友,但是我不太愿意为了游戏的目的而加入React,尽管我认为这会对我的React技能有很大的帮助。我想这个想法有点太大了,所以我需要找到一个小游戏的想法。或者停止做React,为特定的体验制作Wordpress主题,但那并不是那么有趣。也许,只是也许,下次我会做一些与口袋妖怪无关的事。