gpt4 book ai didi

reactjs - Facebook React.js : how do you render stateful components on the server?

转载 作者:行者123 更新时间:2023-12-03 13:00:54 24 4
gpt4 key购买 nike

我认为我在概念上遗漏了使用 React.js 进行服务器端渲染的一些东西

假设我想创建一个页面来显示服务器端数据库中的项目,并带有输入字段来过滤它们。

我想要一个页面:

  • 响应像 /items?name=foobar 这样的 URL
  • 使用 React 输入字段按名称过滤项目
  • 使用 React 组件来显示过滤后的项目列表

假设我有一个公共(public) REST API 来查询客户端的项目。

从概念上讲,我想要在第一次请求时执行的操作(GET/items?name=foobar)是:

  • 我希望我的输入字段显示用户作为参数传递的内容,所以我需要将查询参数('foobar')作为'prop'(如initialName)传递给react组件

所以我尝试了这个:

 // A stateful component, maintaining the value of a query field
var ItemForm = React.createClass({
getInitialState : function () {
return {
name : this.props.initialName
};
},
handleInputValueChanged : function() {
var enteredName = this.refs.query.getDOMNode().value.trim();
this.props.onNameChanged(enteredName);
},
render : function () {

return React.DOM.form({
children : [
React.DOM.label({
children : "System name"
}),
React.DOM.input({
ref : "query",
value : this.state.name,
onChange : this.handleInputValueChanged
})
]
});
}
});
  • 我还必须在服务器上进行数据库查询以获取项目列表,并且将此项目列表作为 ItemList 的“prop”传递(如“initialItems”)

据我了解,我需要一个简单的组件来显示列表,并将其作为“prop”接收:

 // A stateless component, displaying a list of item
var ItemList = return React.createClass({

propTypes : {
items : React.PropTypes.array
},

render : function () {
return React.DOM.ul({
children : _.map(this.props.items, function (item) {
return React.DOM.li({
children : [
React.DOM.span({
children : ["Name : ", item.name].join(" ")
})]
});
})
});
}
});
  • 现在,我需要一个组件来显示整个页面;该组件必须维护整个页面的状态,即查看字段中输入的名称,并进行 API 查询来更新列表项。但是我不明白这个组件如何拥有一个既可以在服务器端工作又可以在客户端渲染的“initialState”。

我试过这个:

 // A stateful react component, maintaining the list of items
var ItemPage = React.createClass({

getInitialState : function () {
// ?????
// This is where I'm sure the problem lies.
// How can this be known both on server and client side ?
return {
items : this.props.initialItems || []
};
},
queryItems : function (enteredName) {

var self = this;

// The field was emptied, we must clear everything
if (!enteredName) {
this.setState({
items : []
});

} else {

// The field was changed, we want to do a query
// then change the state to trigger a UI update.
// The query code is irrelevant, I think.
doQuery(enteredName).then(function (items) {
self.setState({
items : items
});
});
}
},
render : function () {

// I don't want to display the same view
// if there is no results.
// This uses a 'state' property of the page
var results = null;
if (_.isEmpty(this.state.items)) {
results = React.DOM.div({
ref : "results",
children : "No results"
});
} else {
results = ItemListView({
// Here items is a 'prop', the ItemList is technically
// stateless
items : this.state.items
});
}

return React.DOM.div({
children : [
ItemForm({
initialName : this.props.initialName,
onNameChanged : this.queryItems
}),
results
]
});
}
});

这就是我被困住的地方。我可以使用类似以下内容在服务器端渲染内容:

var name = // The name from the query parameters
var items = doQueryOnServerSide(name);
React.renderComponentAsString(ItemPage({
initialName : name,
initialItems : items
});

但是当我尝试编写客户端 JavaScript 时,我应该做什么?我知道我想要在哪里渲染 dom,但是我应该将哪些初始 props 传递给 React 组件?

React.renderComponent(ItemPage({
initialName : ??? // Read the name parameter from URL ?
initialItems : ??? // I don't know yet, and I don't want to make an API call until the user entered something in the input box
});

我尝试过的大多数尝试最终都会导致 DOM 在客户端被“删除”,并显示以下消息:

React attempted to use reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server.

请注意,只有我的 ItemList 组件的标记被删除,所以我认为这是我的组件的实现问题,但我真的不知道从哪里开始。

我走在正确的道路上吗?或者我完全错过了什么?

最佳答案

使用服务器渲染时,您应该始终传递用于在服务器上渲染组件的相同属性。在这种情况下,您需要传递相同的initialItems prop,以便React.renderComponent 获取服务器渲染的标记(只需对props进行JSON化并将其放入对的调用中)渲染组件)。

指定时从initialItems 读取的一般结构对我来说很有意义。这样做可以让您要么制作一个带有预加载数据的组件,要么制作一个没有预加载数据的组件。您需要将初始状态设置为什么取决于您在从头开始渲染全新组件的情况下想要显示的内容。 (如果您总是选择服务器渲染的标记,那么您只需传递 initialNameinitialItems 属性即可。)

希望这是有道理的。

关于reactjs - Facebook React.js : how do you render stateful components on the server?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20978946/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com