我学习反应+火力棒。我还读到了关于React服务器渲染和放大器的信息。我想测试&看看服务器呈现我的应用程序是什么样子。所以我使用ReactDOMServer来渲染我的组件,并且可以渲染我非常简单的组件,但是当我尝试使用rebase包在我的应用程序和Firebase之间同步数据的组件时,我遇到了问题。这是我得到的警告:
警告:setState(...):只能更新安装组件。这个 通常意味着你在componentWillMount()之外调用了setState() 服务器。这是一个无操作。请检查应用程序的代码 成分
这是我的代码:
应用组件:
import React from 'react';
import Header from './Header';
import Orders from './Orders';
import Inventory from './Inventory';
import SampleFishes from '../sample-fishes';
import Fish from './Fish';
import base from '../base';
class App extends React.Component{
constructor(){
super();
this.addFish = this.addFish.bind(this);
this.loadSampleFishes = this.loadSampleFishes.bind(this);
this.addToOrder = this.addToOrder.bind(this);
this.liveUpdateFish = this.liveUpdateFish.bind(this);
this.removeFish = this.removeFish.bind(this);
this.removeOrder = this.removeOrder.bind(this);
this.state={
fishes:{},
orders:{}
};
}
componentWillMount(){
let prevOrder = localStorage.getItem(`${this.props.params.store}-order`);
this.ref = base.syncState(`${this.props.params.store}/fishes`,{
context:this,
state:`fishes`,
then(){
if(prevOrder){
this.setState({orders: JSON.parse(prevOrder)});
}
}
});
}
componentWillUnmount(){
base.removeBinding(this.ref);
}
componentWillUpdate(nextProps,nextState){
localStorage.setItem(`${this.props.params.store}-order`,JSON.stringify(nextState.orders));
}
loadSampleFishes(){
let fishes = {...this.state.fishes,...SampleFishes};
this.setState({fishes});
}
addFish(fish){
let fishes = {...this.state.fishes};
fishes[`fish-${Date.now()}`]= fish;
this.setState({fishes});
}
addToOrder(key){
let orders = {...this.state.orders};
orders[key] = orders[key]+1 ||1;
this.setState({orders});
}
liveUpdateFish(fish,k){
let fishes = {...this.state.fishes};
fishes[k] = fish;
this.setState({fishes});
}
removeFish(key){
let fishes = {...this.state.fishes};
fishes[key] = null;
this.setState({fishes});
this.removeOrder(key);
}
removeOrder(key){
let orders = {...this.state.orders};
delete orders[key];
this.setState({orders});
}
render(){
return (
<div className="catch-of-the-day">
<div className="menu">
<Header tagline="Fresh SeaFood Market"/>
<ul>
{
Object.keys(this.state.fishes).map(key=><Fish addToOrder={this.addToOrder} id={key} key={key} fish={this.state.fishes[key]} />)
}
</ul>
</div>
<Orders orders={this.state.orders} fishes={this.state.fishes} removeOrder={this.removeOrder}/>
<Inventory addFish={this.addFish} loadSampleFishes={this.loadSampleFishes} fishes={this.state.fishes} liveUpdate={this.liveUpdateFish} removeFish={this.removeFish} />
</div>
);
}
}
export default App;
订单组件:
import React from 'react';
import Order from './Order';
import {formatPrice} from '../helpers';
class Orders extends React.Component{
render(){
const orderIDs = Object.keys(this.props.orders);
let list = null;
if(orderIDs.length===0){
list = <li>OOPS there is no item</li>;
}else{
list = Object.keys(this.props.orders).map(key=><Order removeOrder={this.props.removeOrder} fish={this.props.fishes[key]} key={key} index={key} order={this.props.orders[key]}/>)
}
const total = orderIDs.reduce((prev,index)=>{
if(!this.props.fishes[index]) return prev;
if(!this.props.fishes[index].price) return prev;
return prev+this.props.fishes[index].price*this.props.orders[index]},0);
return (
<div className="order-wrap">
<h2>Your Orders</h2>
<ul className="order">
{list}
<li className="total">total is {formatPrice(total)}</li>
</ul>
</div>
);
}
}
export default Orders;
订购组件:
import React from 'react';
import {formatPrice} from '../helpers';
class Order extends React.Component{
render(){
const removeButton = <button onClick={e=>this.props.removeOrder(this.props.index)}>❌</button>
return (
<li><span>{this.props.order}x {this.props.fish.name}</span><span className="price">{formatPrice(this.props.fish.price)}</span>{removeButton}</li>
);
}
}
export default Order;
广告资源:
import React from 'react';
import AddFishForm from './AddFishForm'
class Inventory extends React.Component{
constructor(props){
super(props);
this.returnInventory = this.returnInventory.bind(this);
this.handleChanges = this.handleChanges.bind(this);
}
handleChanges(e,key){
const fish = this.props.fishes[key];
const updatedFish = {...fish,
[e.target.name] : e.target.value
};
this.props.liveUpdate(updatedFish,key);
}
returnInventory(key){
const fish = this.props.fishes[key];
return(
<div className="fish-edit" key={key}>
<input name="name" value={fish['name']} type="text" placeholder="fish name" onChange={e=>this.handleChanges(e,key)} />
<input name="price" value={fish['price']} type="text" placeholder="fish price" onChange={e=>this.handleChanges(e,key)} />
<select name="status" value={fish['status']} onChange={e=>this.handleChanges(e,key)}>
<option value="available">Fresh!</option>
<option value="unavailable">Sold Out!</option>
</select>
<textarea name="desc" value={fish['desc']} type="text" placeholder="fish desc" onChange={e=>this.handleChanges(e,key)}></textarea>
<input name="image" value={fish['image']} type="text" placeholder="fish image" onChange={e=>this.handleChanges(e,key)} />
<button onClick={e=>this.props.removeFish(key)}>- Remove Fish</button>
</div>
)
}
render(){
return (
<div>
<h2>Inventory</h2>
{
Object.keys(this.props.fishes).map(key=>this.returnInventory(key))
}
<AddFishForm addFish={this.props.addFish}/>
<button onClick={this.props.loadSampleFishes}>Load Sample Fishes</button>
</div>
);
}
}
export default Inventory;
鱼类组件:
import React from 'react';
import {formatPrice} from '../helpers';
class Fish extends React.Component{
addOrder(k){
console.log(k);
this.props.addToOrder(k);
}
render(){
let available = this.props.fish.status ==='available';
let buttonText = available?'Order it':'Sold Out';
return (<li className="menu-fish" id={this.props.id}>
<img src={this.props.fish.image} alt={this.props.fish.name}/>
<h3 className="fish-name">{this.props.fish.name}<span className="price">{formatPrice(this.props.fish.price)}</span>
</h3>
<p className="fish-desc">{this.props.fish.desc}</p>
<button disabled={!available} onClick={(e)=>this.addOrder(this.props.id)}>{buttonText}</button>
</li>);
}
}
export default Fish;