我有一个聊天UI,用户应该在其中输入文本并从API响应服务接收一些数据。用户界面工作正常,并且在聊天中显示了用户文本,但是以JSON格式接收的来自API的响应根本没有出现在聊天中(甚至没有来自API的错误消息,该消息应该出现在“消息”中字段,这是应该在其中显示结果的字段。)据我所知,一切都配置正确,但是我不知道render方法是否有些混乱。
注意:开始时处于聊天状态的预配置消息仅用于测试目的。
我发布的第一段代码的componentDidUpdate()方法下的Fetch操作。
import React from "react";
import ReactDOM from "react-dom";
import "./App.css";
import Message from "./Message.js";
class Chatroom extends React.Component {
constructor(props) {
super(props);
this.state = {
chats: [
{
username: "clientUser",
content: <p>Hello World!</p>,
img:
"http://***.jpg"
},
{
username: "user2",
content: <p>Hi,my name is user2.What's up ??</p>
},
{
username: "user3",
content: <p>Hi,my name is user3.What's up ??</p>
},
{
username: "user4",
content: <p>Hi,my name is user4.What's up ??</p>
},
{
username: "userN",
content: <p>Hi,my name is userN.What's up ??</p>,
img: "http://***.jpg"
},
{
username: "user5",
content: <p>Hi,my name is user5.What's up ??</p>
},
{
username: "user6",
content: <p>Hi,my name is user6.What's up ??</p>
},
{
username: "user7",
content: <p>Hi,my name is user7.What's up ??</p>
}
]
};
this.submitMessage = this.submitMessage.bind(this);
}
componentDidMount() {
this.scrollToBot();
}
componentDidUpdate() {
this.scrollToBot();
fetch(
"https://****",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
inputText: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>
})
}
).then(response => response.json())
.then(parsedJSON =>
parsedJSON.results.map((
user
) => ({
username: "BotResponse",
content: `${user.message}',
img: "http://***.jpg"
}))
)
.then(chats =>
this.setState({
chats
})
)
.catch(error => console.log("parsing failed", error));
}
scrollToBot() {
ReactDOM.findDOMNode(this.refs.chats).scrollTop = ReactDOM.findDOMNode(
this.refs.chats
).scrollHeight;
}
提交消息方法:
submitMessage(e) {
e.preventDefault();
this.setState(
{
chats: this.state.chats.concat([
{
username: "clientUser",
content: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>,
img: "http://***.jpg"
}
])
},
() => {
ReactDOM.findDOMNode(this.refs.msg).value = "";
}
);
}
render方法:
render() {
const username = "clientUser";
const { chats } = this.state;
return (
<div className="chatroom">
<h3>
Title
</h3>
<ul className="chats" ref="chats">
{chats.map((
chat //Defines message component
) => (
<Message chat={chat} user={username} />
))}
</ul>
<form className="input" onSubmit={e => this.submitMessage(e)}>
<input type="text" ref="msg" />
<input type="submit" value="Submit" />
</form>
</div>
);
}
}
export default Chatroom;
答案 0 :(得分:1)
问题出在你的思维方式上。您的想法就像是编写带有JS增强功能的纯HTML一样。 React是一个根本的概念转变。您需要忘记很多从普通的JS中学到的知识,才能学习React。在React中,您不会让HTMLElement进行操作,而是使用本地/全局状态和组件属性来声明您的UI。生成的代码更加高效,可维护且无故障。
要回到实际问题,您不应该使用ref
来获取输入值。而是使用onChange
设置邮件的状态,并在以后需要时进行检索。
例如:
export class MessageComposer extends React.Component {
state = {
fields: {
message: ""
}
}
clearField = fieldName => {
this.setState({
fields: {
[fieldName]: ""
}
})
}
onInputChange = e => {
this.setState({
fields: {
[e.target.name]: e.target.value
}
})
}
sendMessage = () => {
const { fields: { message } } = this.state
// Here you send the message contained into `message`.
console.log(message)
// Then you clean the message input value.
this.clearField("message")
}
render () {
const { fields: { message } } = this.state
return (
<div className="MessageComposer__container">
<input
type="text"
name="message"
value={message}
onChange={this.onInputChange}
/>
<button onClick={this.sendMessage}>
Submit
</button>
</div>
)
}
}
编辑:刚刚看到您的提取代码包含JSX。 WTF?
尝试更改以下内容:
body: JSON.stringify({
inputText: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>
})
具有无JSX的版本。传递React组件没有任何意义,因为JSON.stringify
甚至无法序列化函数(好的,您会收到将'Function'或'[Object object]'放入{{1} }在您的后端上)。
像这样的东西
inputText
此外,如果由于任何原因React无法找到您的引用(即组件返回body: JSON.stringify({
inputText: ReactDOM.findDOMNode(this.refs.msg).value
})
或任何其他原因),null
都会抛出或返回inputText
。
如果按照我上面的建议重构代码,则可以执行以下操作:
undefined
答案 1 :(得分:0)
关于您的代码,有很多要讨论的内容。为了使答案简单而集中,我只想谈谈您的fetch api call
,以及为什么您可能看不到前端的内容。
首先,我建议研究React文档中的生命周期方法。您可以找到here。如果该链接断开,则只需转到React的文档页面并搜索“ LifeCycle Methods”。
我提出这个问题的原因是,您每次post
{em}每次都会更新数据,而不是在用户提交聊天消息时更新。因此,在用户提交您的那一刻,您就会调用onSubmit
的{{1}}函数。设置状态将更新帖子。因此,在代码中的任何位置,当您更改状态或更改组件的props时,DOM都会更新,并且setState
将被触发并再次发布。
将您的post api调用放置在componentDidUpdate
函数中。从此更新您的表单:
onSubmit
此更新的onSubmit函数:
submitMessage(e) {
e.preventDefault();
this.setState(
{
chats: this.state.chats.concat([
{
username: "clientUser",
content: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>,
img: "http://***.jpg"
}
])
},
() => {
ReactDOM.findDOMNode(this.refs.msg).value = "";
}
);
}
后端
您要确认这确实是 保存到您的数据库中(可能看起来很明显,但是请仔细检查一下它是否保存了您想要的 并返回了正确的信息,以正确的格式显示在后端上。这可能是问题所在。将您的响应记录到后端控制台,并确保它正确返回了所有内容。
前端
看看如何在获取呼叫中设置状态。我不太确定您是如何发送数据的,但这是使用axios进行后期提取调用的示例。
submitMessage(e) {
e.preventDefault();
fetch(
"https://****",
{
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
inputText: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>
})
}
).then(response => response.json())
.then(parsedJSON => {
parsedJSON.results.map((
user
) => ({
username: "BotResponse",
content: `${user.message}',
img: "http://***.jpg"
}))
}
)
.then(chats =>
this.setState({
chats
})
)
.catch(error => console.log("parsing failed", error));
//for the sake of readability and debugging, you might want to store
that obj in a local variable here and put that variable in place of ...[]
this.setState(
{
chats: [
...this.state.chats,
{
username: "clientUser",
content: <p>{ReactDOM.findDOMNode(this.refs.msg).value}</p>,
img: "http://***.jpg"
}
]
},
() => {
ReactDOM.findDOMNode(this.refs.msg).value = "";
}
);
}
我真的没有什么可以建议的了。我不太确定您要使用提供的资源来实现什么。
注意
在整个代码中您正在做一些事情,我不确定您需要做。但是,我没有在这个答案中解决这个问题,因为我不确定您的项目是什么以及您想要的结果。但这应有助于解决不渲染的问题。如果没有,请查看如何在axios.post("http://****", {
data: this.state.data,
more: this.state.more,
etc: { example: "of", object: this.state.obj }
})
.then(response => {
if (response.status === 200) {
//do something with response.data
//this.setState({ data: response.data})
}
});
中设置状态。
希望这会有所帮助。
我认为您的api调用不需要三个fetch api call
。解析json之后,您可以在此处设置状态。
上面的来源没有给出期望的结果。提取api调用未将数据返回到第二个then调用,因为来自第一个then调用的数据。这是更新的.then
函数。
submitMessage