I am building an interactive Shiny app using Neo4j graph data by using RNeo4j package to connect Neo4j with R.
The app contains a table showing properties of graph data pulled from Neo4j, users can view and change table content (properties of graph data). The changes can be written back to Neo4j as an update of graph data properties. This function can be completed using updateProp
& getOrCreateNode
functiona in RNeo4j package.
However, I have a reactive error.
Below is my code:
library(RNeo4j)
library(dplyr)
library(shiny)
library(shinydashboard)
library(visNetwork)
library(tidyr)
library(sqldf)
library(igraph)
library(plotly)
library(stringi)
library(stringr)
graph = startGraph("http://localhost:7474/db/data/", username = "xxx", password = "xxx")
summary(graph)
# build dashboard
# UI items list
header <- dashboardHeader(
title = "Neo4j"
)
sidebar <- dashboardSidebar(
sidebarMenu (
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "dashboard1",
box(textOutput("aa")),
box(title = "CATEGORY", DT::dataTableOutput("category")),
box(uiOutput("category_status"))
)
)
)
# UI
ui <- dashboardPage(header, sidebar, body)
# Server
server <- function(input, output, session) {
# Query graph data and properties from Neo4j and store them in table format in R
query = "
MATCH (c:Category)
RETURN c.id AS Category, c.Price AS Price, c.status AS Category_Status
"
info = cypher(graph, query) # R Table to store Neo4j data
# Build Shiny output tables
output$i1 <- renderTable(info)
output$category = DT::renderDataTable(info, selection = 'single')
# This is to build the function of change the status of category with 3 options
output$category_status = renderUI({
x = info[input$category_rows_selected, ]
if (length(x)){
selectInput("category_status", "",
c( "Sold", "On Sale","Out of Stock"),
selected = x$Category_Status)
}
})
# Table to examine if the status change was made successfully
output$aa<-renderText(input$category_status)
# Write back the changes made in Shiny to Neo4j using "updateProp" & "getOrCreateNode" function in RNeo4j
if(info$Category_Status[input$category_rows_selected] != input$category_status) {
category_num = as.numeric(substring(info$Category[input$category_rows_selected], 16))
updateProp(getOrCreateNode(graph, "Category", Category = paste("CC_CCAA_AAC.0C-", category_num, sep="")),
status = input$status)
}
}
# Shiny dashboard
shiny::shinyApp(ui, server)
Below is the error message:
Listening on http://127.0.0.1:4401
Warning: Error in .getReactiveEnvironment()$currentContext: Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
55: stop
54: .getReactiveEnvironment()$currentContext
53: .subset2(x, "impl")$get
52: $.reactivevalues
50: server [#44]
Error in .getReactiveEnvironment()$currentContext() :
Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)
By trail and error, the Shiny app can work properly if I remove the code of written the changes back to Neo4j, which is the last part of the code. However, this is the core function of this project.
Also, this written-back function worked properly by standing alone outside of Shiny. So the problem is the interaction between 2 parts.
I am wondering if I can add observeEvent
in Shiny to solve this problem.
Thanks in advance.
As you said the last part of your code caused the problem. The reason behind is that you use reactives
in this code chunk. That is you use input$category_rows_selected
, input$category_status
and input$status
which do not have a fixed value but depend on your interaction with the app.
Depending on what you want to do you have basically 2 options:
isolate
. In this case, however, your code will never be updated when you change the respective inputs.observe
. In this case whenever either of the inputs (as listed above) change its value, this code will be executed. If you want your code chunk to run only if some of the inputs change you can isolate
the inputs you do not want to take a dependency on. For instance this code will be executed whenever input$category_rows_selected
or input$category_status
change but not if input$status
change because it is wrapped in isolate
:
observe({
if(info$Category_Status[input$category_rows_selected] != input$category_status) {
category_num = as.numeric(substring(info$Category[input$category_rows_selected], 16))
updateProp(getOrCreateNode(graph, "Category",
Category = paste("CC_CCAA_AAC.0C-", category_num, sep="")),
status = isolate(input$status))
}
})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.