我正在尝试对ReactJs进行双向绑定并尝试使用LinkedStateMixin。根据从React 0.14开始的React网站,所有插件都被移动到单独的包中:https://facebook.github.io/react/blog/2015/07/03/react-v0.14-beta-1.html所以我通过npm安装了react-addons-linked-state-mixin,但是当我尝试使用它时出现以下错误:
Uncaught TypeError: this.linkState is not a function
我的代码是:
import React, { PropTypes } from 'react';
import TimelineEvent from './TimelineEvent';
import {TimelineEditButton} from './TimelineEvent';
import styles from './Main.css';
import withStyles from '../../../../decorators/withStyles';
import MainView from '../../../MainView';
import SwapBlock from '../../../SwapBlock';
import RoundButton from '../../../RoundButton';
import LightBox from '../../../LightBox';
import Dropzone from 'react-dropzone';
import classnames from 'classnames';
import LinkedStateMixin from 'react-addons-linked-state-mixin';
@withStyles(styles)
class Main extends React.Component {
render() {
let session = this.props.session
let user = this.props.user
return (
<MainView>
<Timeline session={session} user={user} />
</MainView>
);
}
}
class Timeline extends React.Component {
// Hide all Partials
constructor() {
super();
this.state = {
eventTitle: '',
eventPlace: '',
eventLocation: '',
eventDescription: ''
};
this.state['addEventPartial'] = false;
this.state.files = [];
}
openPartial(tag) {
var tags = {};
tags[tag] = true;
this.setState(tags);
var e = document.getElementById("add-timeline-event");
if (!!e && e.scrollIntoView) {
e.scrollIntoView();
}
}
closePartial(tag) {
var tags = {};
tags[tag] = false;
this.setState(tags);
}
openLightbox(tag) {
var tags = {};
tags[tag] = true;
this.setState(tags);
}
closeLightbox(tag) {
var tags = {};
tags[tag] = false;
this.setState(tags);
}
getPartial(tag)
{
return this.state[tag];
}
getLightbox(tag)
{
return this.state[tag];
}
onDrop(files) {
console.log('Received files: ', files);
this.setState({
files: files
});
}
render() {
let session = this.props.session
let user = this.props.user
let isAuth = session.isAuth
let addEvent = {}
let events = []
let data = [{
id: "123",
key: "1",
type: "academic",
time: "2015 - 2016",
title: " MSc Software Engineering",
place: "University of Oxford",
location: "Oxford, United Kingdom",
description: "Lorem impsum",
gallery: []
},{
id: "234",
key: "2",
type: "professional",
time: "2015 - 2016",
title: " MSc Software Engineering",
place: "University of Oxford",
location: "Oxford, United Kingdom",
description: "Lorem impsum",
gallery: [
{url: "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash2/v/t1.0-1/p160x160/10923196_10204583699694173_6145976884213630323_n.jpg?oh=bd235908314ecf0ab5afa8d3f92f5abf&oe=567B51F9&__gda__=1450897067_285c7c8c720c0f130453b37e9ff9b2f8"}
]
},{
id: "567",
key: "3",
type: "misc",
time: "2015 - 2016",
title: " MSc Software Engineering",
place: "University of Oxford",
location: "Oxford, United Kingdom",
description: "Lorem impsum",
gallery: [{
index: 1,
url: "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-ash2/v/t1.0-1/p160x160/10923196_10204583699694173_6145976884213630323_n.jpg?oh=bd235908314ecf0ab5afa8d3f92f5abf&oe=567B51F9&__gda__=1450897067_285c7c8c720c0f130453b37e9ff9b2f8"
}]
}]
// Loop through all Timeline Events
for (var i = 0; i < data.length; i++) {
let directions;
let gallery = [];
if (i % 2 == 0) {
directions = "direction-r";
} else {
directions = "direction-l"
}
for (var j = 0; j < data[i].gallery.length; j++) {
gallery.push(
<a onClick={this.openLightbox.bind(this, "galleryLightbox")}><img alt={data[i].title} className="TimelineViewGalleryImage" src={data[i].gallery[j].url} /></a>
)}
events.push(
<li>
<TimelineEvent
key = {data[i].id}
type={data[i].type}
time = {data[i].time}
title = {data[i].title}
place = {data[i].place}
location = {data[i].location}
description = {data[i].description}
direction = {directions}
session = {session}
user = {user}>
{gallery}
<TimelineEditButton deleteClick={this.openPartial.bind(this, "addEventPartial")}
editClick={this.openPartial.bind(this, "addEventPartial")}
session={session} user={user} eventId={data[i].id} />
</TimelineEvent>
</li>
)
}
// Add Event to timeline Dialog
if (isAuth){
addEvent = (
<form className="AddEventForm">
<SwapBlock show={!this.getPartial("addEventPartial")}>
<div className="AddEventButton">
<RoundButton onClick={this.openPartial.bind(this, "addEventPartial")} color="green">
<span className="EventPlus">+</span>
</RoundButton>
</div>
</SwapBlock>
<SwapBlock show={this.getPartial("addEventPartial")}>
<div className="TimelineBackdrop"></div>
<div className="AddTimelineEvent">
<button className="AddTimelineEventCloseButton" onClick={this.closePartial.bind(this, "addEventPartial")}>
<i className="fa fa-times"></i>
</button>
<h3>Add Event</h3>
<div className="AddEventTitle TimelineFormField">
<input value={eventTitle} className="TimelineInput" placeholder="Title" />
</div>
<div className="AddEventPlace TimelineFormField">
<input valueLink={this.linkState('eventPlace')} className="TimelineInput" placeholder="Place" />
</div>
<div className="AddEventLocation TimelineFormField">
<input valueLink={this.linkState('eventLocation')} className="TimelineInput" placeholder="Location" />
</div>
<div className="AddEventDescription TimelineFormField">
<textarea valueLink={this.linkState('eventDescription')} rows="2" className="TimelineInput" placeholder="Description"></textarea>
</div>
<StartDateSelect />
<EndDateSelect />
<EventTypeSelect />
<div className="AddEventMedia TimelineFormField">
<Dropzone className="Dropzone" activeClassName="DropzoneActive" ref="dropzone" multiple={true} disableClick={false} onDrop={this.onDrop.bind(this)}>
<div>Try dropping some files here, or click to select files to upload.</div>
{this.state.files.length > 0 ?
<div>
<div>{this.state.files.map((file) =>
<div className="DropzoneUploadedImageContainer">
<img className="DropzoneUploadedImage" src={file.preview} />
<br className="clear" />
</div> )}
</div>
<p className="DropzoneFileCount">{this.state.files.length} files</p>
</div> : null}
</Dropzone>
<p className="AddTimelineEventNote">Note: Images only, maximum 4 images and maximum file size is 2 MB</p>
<button className="SaveEventButton btn btn-primary">Save</button>
<button onClick={this.closePartial.bind(this, "addEventPartial")} className="SaveEventButton btn btn-default">Cancel</button>
</div>
</div>
</SwapBlock>
<SwapBlock show={this.getPartial("addEventPartial")}>
<div className="TimelineSeparator"></div>
</SwapBlock>
</form>
);
}
// Render Timeline
return (
<div className="Timeline">
<LightBox show={this.getLightbox("galleryLightbox")}>
<button className="TimelineGalleryCloseButton" onClick={this.closeLightbox.bind(this, "galleryLightbox")}>
<i className="fa fa-times"></i>
</button>
<img src="https://d13yacurqjgara.cloudfront.net/users/14268/screenshots/1934662/taptap_1x.png" />
</LightBox>
<h3><span className="TimelineHeading">Timeline</span>
<div className="TimelineNav">
<button href="#" className="allFilter active">All</button>
<button href="#" className="professionalFilter">Professional</button>
<button href="#" className="academicFilter">Academic</button>
<button href="#" className="miscFilter">Miscellaneous</button>
</div>
<br className="clear" />
</h3>
<div className="TimelineContainer" id="add-timeline-event">
{addEvent}
<ul className="TimelineView">
{events}
</ul>
</div>
</div>
);
}
}
class StartDateSelect extends React.Component {
render() {
return(
<div className="AddEventDescription TimelineFormField">
<h5 className="EventTypeField EventDateField"><span className="EventTypeLabel">Start Date</span></h5>
<div className="EventDateContainer">
<select className="TimelineFormField">
<option selected disabled>Year:</option>
<option value="--">--</option>
<option value="01">2015</option>
<option value="02">2014</option>
<option value="03">2013</option>
</select>
<select className="TimelineFormField">
<option selected disabled>Month:</option>
<option value="--">--</option>
<option value="January">December</option>
<option value="February">November</option>
<option value="March">October</option>
</select>
<select className="TimelineFormField">
<option selected disabled>Day:</option>
<option value="--">--</option>
<option value="2014">31</option>
<option value="2015">30</option>
<option value="2016">29</option>
</select>
</div>
<br className="clear" />
</div>
);
}
}
class EndDateSelect extends React.Component {
render() {
return(
<div className="AddEventDescription TimelineFormField">
<h5 className="EventTypeField EventDateField"><span className="EventTypeLabel">End Date</span></h5>
<div className="EventDateContainer">
<select className="TimelineFormField">
<option selected disabled>Year:</option>
<option value="--">--</option>
<option value="01">2015</option>
<option value="02">2014</option>
<option value="03">2013</option>
</select>
<select className="TimelineFormField">
<option selected disabled>Month:</option>
<option value="--">--</option>
<option value="January">December</option>
<option value="February">November</option>
<option value="March">October</option>
</select>
<select className="TimelineFormField">
<option selected disabled>Day:</option>
<option value="--">--</option>
<option value="2014">31</option>
<option value="2015">30</option>
<option value="2016">29</option>
</select>
</div>
<br className="clear" />
</div>
);
}
}
class EventTypeSelect extends React.Component {
render() {
return(
<div className="AddEventDescription TimelineFormField">
<h5 className="EventTypeField"><span className="EventTypeLabel">Event Type</span>
<button className="EventTypeFieldProfessional"><span className="TypeDot"></span>Professional</button>
<button className="EventTypeFieldAcademic"><span className="TypeDot"></span>Academic</button>
<button className="EventTypeFieldMiscellaneous"><span className="TypeDot"></span>Miscellaneous</button>
</h5>
</div>
);
}
}
export default Main;
我不确定我做错了什么。
有什么想法吗?
由于