в общем у меня проблема. Я хочу отправить сообщение в конечную точку, в которой нужно отправить все сообщения из базы данных в тему веб-сокета, чтобы клиент мог их все получить. Вот мой метод отправки сообщения (я использую MONGODB):
@PostMapping("/send")
public void sendMessage(@RequestBody Message message){
mongoTemplate.insert(message);
simpMessagingTemplate.convertAndSend("/topic/greetings", mongoTemplate.query(Message.class).as(Message.class).all());
}
В общем ничего из ряда вон выходящего, с этим проблем нет, все в тему, все круто. Теперь все это нужно отловить на клиенте, для этого я написал следующий код:
var stompClient: any = null;
const SockJS = require('sockjs-client')
const Stomp = require('stompjs')
function App() {
const [posts, setPosts]: any = useState("")
const [handleInput, setHandleInput] = useState("")
function setValueInput(e: any){
setHandleInput(e.target.value);
}
function sendMessage(e: any){
e.preventDefault();
axios.post('http://localhost:8080/api/send', {
id: Date.now(),
text: handleInput,
})
.then(function (response) {
setHandleInput("");
})
.catch(function (error) {
console.info(error);
});
}
useEffect(function (){
let Sock = new SockJS('http://localhost:8080/ws')
stompClient= Stomp.over(Sock)
stompClient.debug = null
setTimeout(function() {
stompClient.connect({},function (frame: any){
console.info(`Connected: ${frame}`)
stompClient.subscribe("/topic/greetings", function (greeting: any) {
console.info(greeting.body)
const tempParsedJson = JSON.stringify(greeting.body)
console.info(tempParsedJson)
setPosts(tempParsedJson)
});
}, 1200)})
}, [])
return (
<div className = "App">
{posts && posts.map((data: any) => (
<Form key = {data.id} {...data}/>
))}
<div className = {style.dop}>
<input onChange = {setValueInput} value = {handleInput} className = {style.input}/>
<a onClick = {sendMessage} className = {style.button}>Submit</a>
</div>
</div>
);
}
export default App;
Короче, успешно подписываемся на тему, опять все хорошо, но пока мне не нужно получить объекты. В консоли вижу это:
Первое — это то, что я получаю от Java, второе — это то, что я пытаюсь перевести в JSON. После отправки сообщений, по моему коду, мы видим, что я пытаюсь отобразить эти данные отдельно в каждом элементе, но при попытке получаю ошибку:
ОШИБКА posts.map не является функцией
Я надеюсь, что вы можете помочь, я не знаю, что делать. Кстати пробовал через gson перевести List на Java в json, но выводится та же ошибка.. Помоги пожалуйста.. Моя форма:
const Form: React.FC<Props> = ({id, text}) => {
function handleDelete(e: any) {
e.preventDefault();
axios.post('http://localhost:8080/api/deleteMessage', {
id: id,
text: text,
})
.then(function (response) {
})
.catch(function (error) {
console.info(error);
});
}
return (
<div>
<div className = {style.wrapper}>
<div className = {style.coontainer}>
<div className = {style.form}>
<p>{text}</p>
<a onClick = {handleDelete} style = {{display: "inline", margin: "0 20px", color: "white", cursor: "pointer"}}>Удалить</a>
</div>
</div>
</div>
</div>
);
};
export default Form;
Поскольку ваш код является асинхронным и не извлекается немедленно, и может потребоваться время, пока данные не будут получены, ваши данные не будут определены, а сообщения будут пустой строкой до тех пор, пока данные не будут извлечены, тогда он будет обновлен для замены данными
поэтому эта ошибка была выброшена на вашу консоль, потому что экземпляр String не имеет метода с именем «карта».
поэтому, чтобы решить эту проблему, у вас есть решения.
во-первых, добавить тернарный оператор (?) после слова posts, чтобы быть похожим на эти сообщения?.map() это заставит код работать, только если данные существуют и у них есть метод карты (другими словами, если данные представляют собой массив)
или второе решение определяет значение начального состояния как пустой массив
нет, не будет! потому что это все равно, что сказать js, хорошо, если у меня есть сообщения, и эти сообщения содержат карту, тогда сделайте это... но это не так, игнорируйте это и не выдавайте ошибку
Э-э, да, это выдаст эту ошибку, потому что я проверил ее в консоли браузера, и она действительно выдала эту ошибку. Попробуйте сами, если не верите мне. posts?.map(...)
проверяет, является ли posts
ложным, прежде чем пытаться вызвать .map
его, он не проверяет, является ли posts.map
неопределенным (и, следовательно, ложным). Возможно, вы имели в виду что-то вроде posts && posts.map && posts.map(...)
, что делает эту проверку?
да, а также, чтобы избежать этого длинного оператора, сделайте начальное состояние пустым массивом.
Сначала сделайте начальное состояние пустым массивом, как этот фрагмент кода:
const [posts, setPosts]: any = useState([]);
А затем используйте тернарный оператор при использовании функции карты, например:
posts && posts?.map(() => {})
Если posts
— правдивая строка, posts?.map(...)
выбросит posts?.map is not a function
.
Другие ответы указывали на тот факт, что вам нужно инициализировать posts
как массив, когда вы объявляете его с помощью хука useState
в следующей строке:
const [posts, setPosts]: any = useState([]) // [], not ""
но они, похоже, упустили проблему в этом фрагменте кода:
console.info(greeting.body)
const tempParsedJson = JSON.stringify(greeting.body)
console.info(tempParsedJson)
setPosts(tempParsedJson)
greeting.body
выглядело хорошо для меня: судя по вашему первому console.info
выводу, это выглядело как массив, содержащий некоторые объекты, и вы, безусловно, .map
могли бы это исправить, если бы это было так. Однако при дальнейшем рассмотрении, если бы это действительно были проанализированные данные JSON, ваш браузер отобразил бы это по-другому. В частности, вы сможете расширять части данных JSON.
Однако в строке ниже вы не помогаете себе.
Вы берете данные, которые у вас есть в greeting.body
, а затем преобразуете их в строки. Затем вы называете свою переменную, чтобы создать впечатление, что вы «разобрали» JSON, что бесполезно. Вы не разобрали JSON здесь, на самом деле вы сделали наоборот. Синтаксический анализ — это процесс преобразования строки JSON в объекты и массивы JavaScript, преобразование строк — это другой способ.
Следовательно, исправление состоит не в том, чтобы вызывать JSON.stringify
на greeting.body
, а вместо этого вызывать JSON.parse
на нем.
Ваш сервер Java мог отправить JSON по сети на ваш интерфейс. Я ожидаю, что Axios проанализирует этот JSON в объекты JavaScript для вас, чтобы вы могли сразу начать их использовать, но по причинам, в которых я не уверен, это не так.
Обратите внимание, что у меня нет вашего бэкенда и я не запускал этот код, так что могут быть другие проблемы. Я только объясняю, как исправить ошибку «posts.map не является функцией».
Я решил свою проблему так же, как вы сказали, я разобрал строку, которую я получаю с сервера, в объекты js, используя: JSON.parse(greeting.body), спасибо!
@panic08: рад, что ты смог решить свою проблему. Извиняюсь, если язык моего ответа был, возможно, слишком критическим; Я переработал его и немного смягчил. Кажется, я ошибался, полагая, что Axios возвращает вам проанализированные объекты JS. Я ожидал, что он сделает это для вас, я не уверен, почему этого не произошло.
Если
posts
— правдивая строка,posts?.map(...)
выброситposts?.map is not a function
.