簡體   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