我的第一个StackOverflow问题,一直敲打我大约4个小时!
我正在构建一个包含图片库部分的反应页面。在桌面网站上,当用户点击图像时,它会启动一个Bootstrap模式弹出窗口,该模式应该显示所点击的绘画(标题,大小,类型和媒体)和更大的图像的详细信息。
我有模态工作(不需要像react-bootstrap这样的特殊库)但是无论点击哪个图像,模态只显示图像和设置中第一个图像的细节。
我尝试过各种各样的道具和状态排列,尝试功能和类组件,似乎没有任何效果。
奇怪的是,如果我查看chrome dev工具中的每个组件反应DOM,每个图像的道具都会正确设置,即使在渲染模态的类中......但在实际渲染的页面中,它不起作用
在我的代码中,我们有一个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">×</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'));
任何指针都将非常感谢!
答案 0 :(得分:0)
尝试从每个组件中删除此类代码,因为您不需要:
```的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
。让我们看看。
干杯!
答案 1 :(得分:0)
模态必须是一次只有一次!并将数据传递给该模态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>
);
}
}
答案 2 :(得分:0)
您的问题可能是因为您正在渲染<More />
组件,并且模式的id
内始终是相同的。
因此,您的第<a data-toggle="modal" data-target="#Modal"> </a>
行始终定位id="Modal"
。我怀疑你渲染的html实际上是无效的,因为你的id必须在页面上是唯一的。
如果您更改每个呈现的模式的ID,请确保data-target
链接到正确的模式,然后它应该有效。
答案 3 :(得分:0)
您正在将组件的道具保存到其状态 - 这违反了React的理念(维护单一的事实来源)并且经常会导致错误。
当其道具或其状态发生变化时,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" />
时会发生什么? 道具会更新,因此该组件会重新渲染。不幸的是,组件状态没有改变,因此渲染的输出是相同的。
我们如何解决这个问题?我们保持一个事实来源。这意味着任何信息都存储在应用程序中的一个且只有一个位置。在Simple组件的情况下,这个地方在道具中。我们应该重构它以在render方法中使用props:
class Simple extends React.Component {
render() {
return (
<div>{this.prop.name}</div>
);
}
}
现在我们已经完成了它甚至不再需要成为一个类了:
const Simple = ({ name }) => (
<div>{name}</div>
);
您现在应该进行此重构,因为将现在或将来破坏您的应用。
查看您的具体问题,问题很可能是您最终使用ID为“#Modal”的多个div。您创建的每个元素都会创建一个具有该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库就是一条很好的路径。
答案 4 :(得分:0)
使用标签时,不必使用datta-toggle,而应使用href(从引导文档中获取)
注意:对于元素,请省略数据目标,而应使用href =“#modalID”