簡體   English   中英

反應道具/狀態未傳遞到模態窗口

[英]React props/state not passing to modal window

我的第一個StackOverflow問題已經使我的頭跳了大約4個小時!

我正在建立一個具有圖像庫部分的反應頁面。 在桌面站點上,當用戶單擊圖像時,它將啟動Bootstrap模態彈出窗口,該彈出窗口應顯示單擊的繪畫的詳細信息(標題,大小,類型和媒體)和更大的圖像。

我已經有了模態工作(不需要任何特殊的庫,例如react-bootstrap),但是無論單擊哪個圖像,模態只顯示圖像和集合中第一個圖像的細節。

我已經嘗試了道具和狀態的各種排列,嘗試了功能和類組件,但似乎沒有任何效果。

奇怪的是,如果我看着chrome dev工具中的每個組件都對DOM做出反應,那么即使在渲染模式的類中,每個圖像的props也都正確設置了……但是在實際的渲染頁面中,它不起作用。

在我的代碼中,我們有一個Gallery組件,其中包含許多Holder組件,每個Holder包含一個PortfolioItem,而PortfolioItem包含一個名為More的組件,用於處理模式。 當每個Holder組件定義道具時,它們會向下傳遞到每個PortfolioItem(當我在圖庫中獲取正確的圖像和詳細信息時,它們會起作用),我只希望這些相同的道具顯示在模式中。

import React from 'react';
import ReactDOM from 'react-dom';


class PortfolioItem extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        url: props.url,
        title: props.title,
        type: props.type,
        size: props.size,
        media: props.media
    };
}

render() {
    return (
        <div className="ot-portfolio-item">
            <More url={this.state.url} title={this.state.title} type={this.state.type} size={this.state.size}
                  media={this.state.media}/>
            <figure className="effect-border">
                <img src={this.state.url} className="img-responsive portfolio-img" alt={this.state.title}/>
                <figcaption>
                    <h2 className="paintingTitle">{this.state.title}</h2>
                    <p className="paintingDetail">{this.state.type}, {this.state.size}, {this.state.media}</p>
                    <a data-toggle="modal" data-target="#Modal"> </a>
                </figcaption>
            </figure>
        </div>
    );
}
}

class More extends React.Component {
constructor(props) {
    super(props);
    this.state = {
        url: props.url,
        title: props.title,
        type: props.type,
        size: props.size,
        media: props.media
    };
}

render() {
    return (
        <div className="modal fade" id="Modal" aria-labelledby="Modal-label">
            <div className="modal-dialog">
                <div className="modal-content">
                    <div className="modal-header">
                        <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span
                            aria-hidden="true">&times;</span></button>
                        <h4 className="modal-title">{this.state.title}</h4>
                    </div>
                    <div className="modal-body">
                        <img src={this.state.url} alt={this.state.title} className="img-responsive"/>
                        <div className="modal-works">
                            <span>{this.state.type}</span>
                            <span>{this.state.size}</span>
                            <span>{this.state.media}</span>
                        </div>
                    </div>
                    <div className="modal-footer">
                        <button type="button" className="close btn btn-default" data-dismiss="modal"
                                aria-label="Close">Close
                        </button>
                    </div>
                </div>
            </div>
        </div>
    );
}
}


const Holder = (props) => {
return (
    <div className="col-sm-6 col-md-4 col-0-gutter holder">
        <PortfolioItem url={props.url} title={props.title} type={props.type} size={props.size} media={props.media}/>
    </div>
);
};

const Gallery = () => {
return (
    // When adding a new painting, just copy a <Holder/> in correct orientation section, and change the props!
    <div>
        {/* Landscape */}
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/girl.jpg" title="#Disengaged" type="Acrylic"
                size="24 by 16 inches" media="Board"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/swimming.jpg" title="Submerge" type="Acrylic"
                size="24 by 16 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/staithes.jpg" title="Staithes 2015" type="Acrylic"
                size="24 by 16 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/ladies.jpg" title="Nederlandes Meisjes" type="Acrylic"
                size="24 by 16 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/park.jpg" title="Family Stroll" type="Acrylic"
                size="24 by 16 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/mexican.jpg" title="Tree Of Life" type="Acrylic"
                size="12 by 10 inches" media="Canvas"/>

        {/* Square */}
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/face.jpg" title="Attitudes Of Colour" type="Acrylic"
                size="19.5 by 19.5 inches" media="Board"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/lee.jpg" title="Lee" type="Acrylic"
                size="19.5 by 19.5 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/boat.jpg" title="Drift Away" type="Acrylic"
                size="12 by 12 inches" media="Board"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/cindyself.jpg" title="Prizeworthy" type="Acrylic"
                size="19.5 by 19.5 inches" media="Canvas"/>

        {/* Portrait */}
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/diving.jpg" title="Ascent" type="Acrylic"
                size="32 by 40 inches" media="Ply"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/bluehair.jpg" title="Untitled" type="Acrylic"
                size="10 by 12 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/beach.jpg" title="Namaste" type="Acrylic"
                size="19.5 by 23.5 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/danielle.jpg" title="Concrete Jungle" type="Acrylic"
                size="19.5 by 23.5 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/africa.jpg" title="Untitled" type="Acrylic"
                size="19.5 by 23.5 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/sealady.jpg" title="Aqua Blue" type="Acrylic"
                size="32 by 40 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/violinman.jpg" title="Nightfall" type="Acrylic"
                size="11 by 14 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/indiangirl.jpg" title="Transition" type="Acrylic"
                size="19.5 by 23 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/indianboys.jpg" title="Backpacker's Tales" type="Acrylic"
                size="32 by 40 inches" media="Canvas"/>
        <Holder url="https://dgtqqzvj8521c.cloudfront.net/indianwoman.jpg" title="Journey" type="Acrylic"
                size="19.5 by 23.5 inches" media="Board"/>
    </div>
);
};

const App = () => {
return (
    <Gallery/>
);
};

ReactDOM.render(<App/>, document.getElementById('root'));

任何指針將不勝感激!

您的問題可能歸結為您正在渲染<More />組件,並且模態的id內始終相同。

因此,您的<a data-toggle="modal" data-target="#Modal"> </a>始終以id="Modal"為目標。 我懷疑您呈現的html實際上是無效的,因為您的ID在頁面上必須是唯一的。

如果您更改了所呈現的每個模態的ID,請確保將data-target鏈接到正確的模態,然后它應該起作用。

嘗試從每個組件中刪除這種阻止代碼,因為您不需要:

```JS

constructor(props) {
    super(props);
    this.state = {
        url: props.url,
        title: props.title,
        type: props.type,
        size: props.size,
        media: props.media
    };
}

```

例如:

render() {
let {url, title, size, type, media} = this.props;
    return (
        <div className="ot-portfolio-item">
            <More url={url} title={title} type={type} size={size}
                  media={media}/>
            <figure className="effect-border">
                <img src={url} className="img-responsive portfolio-img" alt={title}/>
                <figcaption>
                    <h2 className="paintingTitle">{title}</h2>
                    <p className="paintingDetail">{type}, {size}, {media}</p>
                    <a data-toggle="modal" data-target="#Modal"> </a>
                </figcaption>
            </figure>
        </div>
    );
}

在您的組件中直接使用prop.url 讓我們看看。

干杯!

模態必須被貶低一次! 然后您將數據傳遞給該模式onClick

class App extends React.Component {
 state = {
  data: {},
 }
sendData = (data) => {
 this.setState({ data });
}

render() {
 return (
  <div>
    <More data={this.state.data} />
    <Gallery sendData={this.sendData} />
  </div>
 );
 }
}

您正在將組件的props保存到其狀態-這違反了React的哲學(保持單一事實來源),並且經常會導致bug。

當React組件的props或狀態改變時,React組件將重新渲染,但是構造函數將不會重新運行。 使用這個簡化的組件:

class Simple extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      name: props.name
    }
  }

  render() {
     return (
       <div>{this.state.name}</div>
     );
  }
}

當我們最初渲染<Simple name="Alex" />然后將“ Alex”設置為狀態,該組件將進行渲染,一切看起來都很好。 如果將其更改為<Simple name="Steve" />那會發生什么? 道具會更新,因此組件會重新渲染。 不幸的是,組件狀態沒有改變,因此渲染的輸出是相同的。

我們該如何解決? 我們維護真理的一種來源。 這意味着任何一條信息都存儲在應用程序的一個位置中,並且只有一個位置。 對於簡單組件,此位置在道具中。 我們應該重構它以在render方法中使用props:

class Simple extends React.Component {   
  render() {
     return (
       <div>{this.prop.name}</div>
     );
  }
}

現在我們已經完成了,它甚至不需要再成為一個類:

const Simple = ({ name }) => (
  <div>{name}</div>
);

您應該立即進行此重構,因為它立即或將來破壞您的應用程序。

查看您的特定問題,該問題最有可能導致您以id為“ #Modal”的多個div結束。 您創建的每個More元素都會創建一個具有該ID的div。 要將代碼分解為更簡單的形式,請使用:

const PortfolioItem = ({ name, url }) => (
  <div>
    <a data-toggle="modal" data-target="#Modal"> </a>
    <More name={name} url={url}
  </div>
);

const More = ({ name, url }) => (
  <div id="Modal">
    <a href={url}>{name}</a>
  </div>
);

我們真正需要的是每個模式都有唯一的ID,因此不會混淆哪個模式被觸發。 我們可以簡單地通過使用名稱prop作為id來做到這一點:

const PortfolioItem = ({ name, url }) => (
  <div>
    <a data-toggle="modal" data-target={name}> </a>
    <More name={name} url={url}
  </div>
);

const More = ({ name, url }) => (
  <div id={name}>
    <a href={url}>{name}</a>
  </div>
);

您可能可以找到更適合用作ID的道具,或者可以使用使用數組索引或隨機字符的解決方案。 確切的ID無關緊要-對於每對PortfolioItem和更多項,它們僅需要唯一。

還值得注意的是,這不是在React中處理模式的慣用方式。 通常,模式的打開/關閉狀態存儲在React自身中,並使用點擊處理程序進行處理。 如果您想沿着這條路走得更遠,那么react-modal庫是一條理想的走之路。

使用標簽時,不必使用datta-toggle,而應使用href(從引導文檔中獲取)

注意:對於元素,請省略數據目標,而使用href =“#modalID”代替

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM