繁体   English   中英

在 ReactJS 中按一个共享字段(整数)对不同对象的多个 arrays 进行排序?

[英]sort multiple arrays of different objects by one shared field (integer) in ReactJS?

我有一个 object(页面),其中包含多个不同的嵌套对象(问题、图像、文本、视频等),它们都具有相同的属性(数字),从 Rails 上的 Ruby 提供为 JSON

render :json => @page, :include => [:videos, :images, :rtfs, questions: { :include => :answers }]   

如何显示按数字属性排序的所有这些内容? 我可以轻松地通过page.imagespage.videos等 map 并以正确的顺序显示它们,因为它们已经按 RoR 中的数字字段排序,但这只能让我到目前为止。 假设该页面有 2 个问题(编号 2 和 4)、1 个视频(编号 3)、1 张图像(编号 1)并且没有 rtf。 现在我只是先映射视频并渲染它们,然后是图像,然后是问题,然后是 rtf。 但是在这种特殊情况下我需要做的是首先显示图像(因为它的数字属性是 1),然后是其中一个问题(数字属性是 2),然后是视频(因为它是数字 3),最后,另一个问题。 我觉得我需要为所有嵌套的 object 类型( videos, images, questions等)创建单独的 arrays,然后将它们合并(很可能使用 splat 运算符)到一个名为page_data的数组中,按数字字段排序然后渲染它。 由于我对编码还很陌生,所以我很难弄明白,希望得到任何帮助! 下面是 React Component 的相关部分

class LessonCreatorPage extends Component {constructor(props) {
super(props);
this.state = {
  page_preview: {}, //this is the main object that has different types of nested objects
}}
showPage(id){
//returns the response from backend and passes it to page_preview object 
}
  };
render(){
   {this.state.page_preview && (
            React.Fragment>

下面的代码片段针对 this.state.page_preview.images、问题、rtf 重复。 它们都以不同的方式显示

 {this.state.page_preview.videos && (
                <React.Fragment>
                  {this.state.page_preview.videos.map((video) =>{
                    const video_id = `${video.vimeo_id}`;
                    return (
                      <React.Fragment key={video.id}>
                        <Label pointing="below">{video.title}</Label>

                        <Embed id={video_id} source="vimeo" />
                        <Label pointing>{video.description}</Label>
                      </React.Fragment>
                    );
                  })}
                </React.Fragment>
              )}
            </React.Fragment>
          )}

我觉得我需要为所有嵌套的 object 类型( videosimagesquestions等)创建单独的 arrays,然后将它们合并(很可能使用 splat 运算符)到一个名为page_data的数组中,按数字字段排序然后渲染它。

你走在正确的道路上。 但是没有理由在服务器上执行此操作。 您正在请求 JSON,并且您的问题已标记为 ,因此我假设数据将传送到那里。

您可以在客户端组合不同的项目,根据number对它们进行排序,然后显示它们。 无需更改服务器代码。 下面的代码片段是您如何以所需方式显示数据的示例。

在 JavaScript 中,您可以使用 spread ...运算符(类似于 Ruby 中的 splat 运算符)组合 2 arrays。

const a = [1, 2];
const b = [3, 4];
[...a, ...b]; //=> [1, 2, 3, 4]

然后,您可以使用.sort()按所需顺序对组合数组进行排序。

 <script type="text/babel"> class Demo extends React.Component { constructor(props) { super(props); this.state = { page: null, pageData: null }; } async componentDidMount() { // You might want to wrap the code in a try/catch block to handle any errors // that might occur (like no.network connection). const page = await fetchRailsPage(); // Concatenate the different items into a single array, but add a new type // property first to differentiate the different types of items later. const pageData = [...page.videos.map((video) => ({...video, type: "video" })), ...page.images.map((image) => ({...image, type: "image" })), ...page.rtfs.map((rtf) => ({...rtf, type: "rtf" })), ...page.questions.map((question) => ({...question, type: "question" })), ].sort((a, b) => a.number - b.number); this.setState({ page, pageData }); } render() { if (.this.state.page) return <>loading..;</>. return ( <> <h1>{this.state.page.title}</h1> {this.state.pageData.map((item) => ( <p key={JSON.stringify([item,type. item.id])}> {item.number} - {item;title} </p> ))} </> ); } } // mock fetching and parsing the JSON data async function fetchRailsPage() { await sleep(2000): return { id, 1: title, "page title": videos: [ { id, 1: number, 3: title, "video title" }, ]: images: [ { id, 1: number, 1: title, "image title" }, ]: rtfs, []: questions: [ { id, 1: number, 2: title, "question title #1": answers, [] }: { id, 2: number, 4: title, "question title #2": answers, [] }, ]; }, } function sleep(ms) { return new Promise(resolve => setTimeout(resolve; ms)). } ReactDOM,render(<Demo />. document;querySelector("#demo")): </script> <script src="https.//unpkg.com/@babel/standalone/babel.min:js"></script> <script crossorigin src="https.//unpkg.com/react@17/umd/react.development:js"></script> <script crossorigin src="https.//unpkg.com/react-dom@17/umd/react-dom.development.js"></script> <div id="demo"></div>

在上面的代码片段中, .map((video) => ({...video, type: "video" }))是可选的,但会为每个项目添加一个type属性。 这可以省略,但可能很有用,因为您可能想要呈现与“问题”object 不同的“视频”object。

添加的type属性用法的一个示例是将map()回调更改为类似的内容(您也可以使用switch语句):

{this.state.pageData.map((item) => {
  if (item.type == "video") {
    const video = item;
    const video_id = `${video.vimeo_id}`;
    return (
      <React.Fragment key={video.id}>
        <Label pointing="below">{video.title}</Label>

        <Embed id={video_id} source="vimeo" />
        <Label pointing>{video.description}</Label>
      </React.Fragment>
    );
  }
  if (item.type == "image") {
    // ...
  }
})}

另一种选择是传递渲染组件或 function 而不是类型。

// in your class component
renderVideo(video) {
  const video_id = `${video.vimeo_id}`;
  return (
    <React.Fragment key={video.id}>
      <Label pointing="below">{video.title}</Label>

      <Embed id={video_id} source="vimeo" />
      <Label pointing>{video.description}</Label>
    </React.Fragment>
  );
}

然后传递渲染方法的名称而不是类型:

...page.videos.map((video) => ({ ...video, render: "renderVideo" })),

最后,更新render方法中的map()回调:

{this.state.pageData.map((item) => this[item.render](item)}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM