我的反应传播存在问题。 我使用此方法在
内呈现带有p标签的div标签。private renderTags(tag: Tags, index: number) {
return <div>
<div onClick={(e) => { e.stopPropagation(); this.collectTags(tag); }}>
<p className={styles.tag}># {tag.title} <i className="ms-Icon ms-Icon--CirclePlus"></i></p>
</div>
</div>
}
该方法从渲染器中被调用,如下所示:
<div className={styles.tagsContainer}>
{this.state.items.slice(0, 12).map((w, index) => this.renderTags(w, index))}
</div>
如您所见,renderTags方法调用了数组中的每个项目。
第一种方法的想法是,当用户单击将元素发送到数组的一个元素时,问题是当我单击这些元素中的一个时,所有元素都会发送到数组。我通过将类名添加到clicked元素中进行测试(仅出于检查原因),当我单击其中一个元素时,所有元素都获得类名,我可以看到出现了相同的行为。
如何停止这种传播?顺便说一下,这是听到点击并将其放置在数组中的方法:
private collectTags(newTag: Tags): any {
//this.setState({ savingSettings: true, tagActive: true });
let selectedTags: Tags[] = this.state.selectedTags;
selectedTags.push(newTag);
this.setState({
selectedTags: selectedTags,
hideSaveButton: false
});
return selectedTags;
}
更新
更好地发布整个代码:
import * as React from 'react';
import { CacheManager } from "../../common/CacheManager";
import { ITagsDataProvider } from "../../interfaces/ITagsDataProvider";
import Tags from "./Tags";
import styles from './TagsContainer.module.scss';
import { Dialog, DialogFooter } from 'office-ui-fabric-react/lib/Dialog';
import { DefaultButton } from 'office-ui-fabric-react/lib/Button';
export interface ITagsContainerProps {
provider: ITagsDataProvider;
}
export interface ITagsContainerState {
items: Tags[];
allTags: Tags[];
selectedTags: Tags[];
savingSettings: boolean;
currentTagsIndex: number;
activeTile: number;
hideDialog: boolean;
hideSaveButton: boolean;
}
export default class TagsContainer extends React.Component<ITagsContainerProps, ITagsContainerState> {
private readonly cacheKey = "TagsLinks";
constructor(props: ITagsContainerProps) {
super(props);
this.state = {
items: [],
allTags: [],
selectedTags: [],
savingSettings: false,
currentTagsIndex: -1,
activeTile: -1,
hideDialog: true,
hideSaveButton: true
}
}
public componentDidMount(): void {
var cacheManager = new CacheManager();
var cachedValue = cacheManager.get(this.cacheKey);
//If there are cached values update the state
if (cachedValue) {
this.setState({
items: cachedValue,
allTags: [],
savingSettings: false,
currentTagsIndex: -1
});
return;
}
this.props.provider.getAllTags().then((tags) => {
if (tags != null) {
cacheManager.set(this.cacheKey, tags);
}
this.setState({
items: tags,
allTags: [],
});
});
}
private renderTags(tag: Tags, index: number) {
return <div>
<div onClick={(e) => this.onTagClick(tag, e)}>
<p className={styles.tag}># {tag.title} <i className="ms-Icon ms-Icon--CirclePlus"></i></p>
</div>
</div>
}
private onTagClick(tag: Tags, e: React.MouseEvent<HTMLDivElement>) {
e.stopPropagation();
this.collectTags(tag);
}
private collectTags(newTag: Tags): any {
this.setState({
selectedTags: {
...this.state.selectedTags,
newTag
},
hideSaveButton: false
});
}
private saveSettings(): void {
let sTags = this.state.selectedTags;
this.setState({
items: sTags
});
console.log('SELECTED TAG ' + this.state.items);
var cacheManager = new CacheManager();
cacheManager.set(this.cacheKey, sTags);
this.props.provider.saveSettingsData(sTags).then(() => {
this.setState({
savingSettings: false
});
});
}
// Render the tags in the dialog box
private onRenderDialog = (tag: Tags, index: number): JSX.Element => {
return (
<div className={styles.tag} onClick={(e) => { e.stopPropagation(); this.collectTags(tag); }}>
<span># {tag.title} <i className="ms-Icon ms-Icon--CirclePlus"></i></span>
</div>
)
}
public render(): JSX.Element {
return <div className={styles.tagCloud}>
<div>
<h1>What are you interested in?</h1>
<p>We'll show you more stories from the topics you pick below</p>
</div>
<div>
<div className={styles.tagsContainer}>
{this.state.items.slice(0, 12).map((t, index) => this.renderTags(t, index))}
</div>
<div>
<a className={styles.allItemsLink} href="#" onClick={this._showDialog}>View all topcis</a>
</div>
<div>
{ this.state.hideSaveButton === false ? <DefaultButton
text="Done"
style={{ backgroundColor: '#ff0033', color: '#ffffff' }}
onClick={(e) =>{e.stopPropagation(); this.saveSettings()}}
/> : null}
</div>
</div>
<Dialog
hidden={this.state.hideDialog}
onDismiss={this._closeDialog}
containerClassName={'ms-dialogMainOverride ' + styles.textDialog}
modalProps={{
isBlocking: true,
}}>
<div className={styles.tagsDialogContainer}>
{this.state.allTags.map((t, index) => this.onRenderDialog(t, index))}
</div>
<DialogFooter>
<DefaultButton
style={{ backgroundColor: '#ff0033', color: '#ffffff' }}
onClick={this._closeDialog}
text="Done"
/>
</DialogFooter>
</Dialog>
</div>
}
private _showDialog = (): void => {
this.setState({ hideDialog: false });
this.props.provider.getAllTags().then((items) => {
this.setState({ allTags: items });
})
};
private _closeDialog = (): void => {
this.setState({ hideDialog: true });
}
}
最好的问候 美国
答案 0 :(得分:0)
首先,您需要创建单独的事件处理方法,例如onTagClick
。
private renderTags(tag: Tags, index: number) {
return <div>
<div onClick={e => this.onTagClick(e, tag)}>
<p className={styles.tag}># {tag.title}
<i className="ms-Icon ms-Icon--CirclePlus"></i>
</p>
</div>
</div>
}
private onTagClick(tag: Tags, e: React.MouseEvent<HTMLElement>) {
e.stopPropagation();
this.collectTags(tag);
}
另一个问题-您正在直接更改状态,这在React中是不允许的。
// Here you creating the link to array named `selectedTags`.
let selectedTags: Tags[] = this.state.selectedTags;
// and here you mutating your state directly
selectedTags.push(newTag);
只需在添加新项目或使用价差运算符之前复制阵列即可。
private collectTags(newTag: Tags): any {
this.setState({
selectedTags: {
...this.state.selectedTags,
newTag
},
hideSaveButton: false
});
}
此外,不要忘记将上下文绑定到构造函数中的collectTags
方法。
constructor(props) {
super(props);
...some code if you have...
this.collectTags = this.collectTags.bind(this);
}
希望有帮助。