- So I think we're all ready to go, and welcome everyone. I hope you had a good
time and you have already, you've adjusted for NODES. Don't forget to come to NODES. There's a ton of good content and sessions and lots of other things. I can definitely
recommend this and there's a lot of app development content as well. So we also have a new agenda page which looks much nicer than before. So you can see if you
spot the new agenda page is live here. So make sure to join us
for a full day next Tuesday only six days to go. Okay, today we want to
talk about something that my colleague Adam built. So if you built apps,
usually you would connect to an API backend, graphic API or other API rest API that kind but if you really just truly want to build a proof of concept or quick prototype or demo app or a graphic for Neo4j desktop, then
you don't have a backend and you connect directly to database to just show the feasibility of something, to convince your boss to
run the project of Neo4j and for prototypes like this, it's kind of a lot of boiler plate to kind of do the driver connection, connection
dialogue, and all this stuff. It's kind of a little bit too competitive. So Adam gave it a try and turn
it into an usable component and then high order component
and react hooks basically. So as you can see here on the
tweet we have a react provider and then if you have hooks
that you can use from here, so Adam created this use Neo4j project that has have these react hooks and you can just quickly
use this and here are some usage examples that we'll look into later, but what I wanted to start up with is also put
together an starter kit which is here and that
you want to try to use. Okay, and this starter card, it's really just showing how to connect to Neo4j and how to do this, so I have cloned a starter kit here and just cloned it into new name and then at dollar dependencies
and run yarn start. And if I run yarn start,
it gives me a UI like this and UI like this to connect to Neo4j and I have my local desktop running the first
single movie database as such. So, and if I connect to Neo4j then it tells me
you have so many notes in the database, okay, that's good. So that's kind of the
minimal startup as such. If you look at the code of the startup, Oh, sorry ,that's the wrong one. If you look at the code of to start, we basically just instantiate or get the Neo4j provider from use-neo4j which is the high order component. We can pass in some stuff,
there's more details on what you can pass in
on the only documentation but you can also, I think you
can also leave this all off. Think you don't, you actually
need to pass anything in and it should also
work out of the hook. Out of the hooks like this, let's see, then it doesn't have one
footer and then header. So if she just want to have
minimal, no Chrome connection dialogue that's this, right. And otherwise, well, that's it. So you don't have to create
a driver port or driver or stuff like that. That's all under the, under the hood. And then basically in our app, the only
thing that's happening you're getting posts, we're not getting posted in anything we just kind of use this this hook, which is like
cross coding consultants. So they are available to
the, to the whole app. And do you hooks internally manager driver and sessions and stuff like that. So there's quite a lot of
methods for reading, writing to Neo4j and also some
convenience methods as well. And so I have to use
useReadCypher hook where js can pass a query and I think it can also
pass set of parameters. So perhaps you can do this to change this. So for instance, you want to
pause parents, it's a record. So my type script was non-existence
or I probably don't need to key or name and let's say Tom Hanks. So because I've a movie data dataset I want to see how many
person name name, return, let's say I want to see how
many movies he acted in or yeah. So I want to find Tom Hanks and I pass in the parameter here. So if I run this again it should show me if I
connect here 12 movies. So there's my query and then 12 movies. Okay. And this hook
has a bunch of returns. So it has a complex return type, it gives back the suffer
statement, gives back errors if it's loading and then the
first order or to other things. So does this kind of fussing all this thoughts
by about what sort of course things that you can get the, so it's in Neo4j results state,
which you can have a look at and this is kind of for
similar results, right? So you basically, it, you
can floating can do loading. If, if that's an error,
then you show the error. And if it's not loading,
we get our count back from our first record and output this and the
loading things, interesting. Oh, Adam just assigns
the result here, so okay. No premature returns, but kind
of just wrapping this year. So does this basically what's shown in the in the dif here, this suffer statement, and then it is an error or loading, or the actual assault? Okay. So much for the starter. I think just not much more. I don't know if there are tests and so
we should probably test also for who to start as well to
make sure that the stuff works. Okay, but now we wanted to
use this in our own apps. So first of all, I did
an graph visualization, I Twitch streamed a while ago where I used a component
to render a graph. And I think I just
created an hard-coded form for, for login. So the code for this is in my three
fourths graph, repository here here would I am doing well,
having fun with react. So after doing a lot of meeting heavy days and yesterday long training,
it's nice to do some coding. I don't get too much
to do this these days. So the Twitch sessions
are with good opportunity. So this is this app and I just have it locally
on my machine as well. And if you look at this,
I think this is this one. We have the App.js, so it's not a TypeScript,
it's in an App.js here. And we get basically the
driver from Index.js, I think. So all this stuff should
be able to delete now. So let me be really brave. And I just delete all. Oh no, I should probably first add, use Neo4j my, here. npm, add, use-neo4j here. Come on. So we should see use Neo4j coming up here. This one should have used yarn I guess. Yarn add, you have to do safe in yarn. I forgot. Now we have used Neo4j here I know you should be able to use it. So if I'm going to be brave I should be able to delete
just a bunch of codes right? So we don't need
Neo4j driver anymore. And this stuff you don't need any more because you just want to have an, we should import in Neo4j provider. Import Neo4j provider from use Neo4j. And then we just have a Neo4j provider as in high order component and then we don't need to
pass a driver to our app. We just use our app. So that's step number one,
should probably be able to remove Neo4j driver from our
explicit dependencies because it comes in with use Neo4j. So it should always be
the up to date version. So that got quite a lot easier. And then here in my app, I don't get
passed into driver anymore. So the app is just an app and
we just call CypherViz here. And in CypherViz we don't get passed in a
driver as well, but we would. So it is all query, this is
all data and here's load data. And so what you would do here is actually it's a good question. You would import , what's
it called use cipher read? I have to sneak into the, it's called useReadCypher from use-neo4j Okay, useReadCypher and
then I should be able in my load function, we
don't need a session. Actually, that's a good question for Adam. So, and then you should
actually just be able to run useReadCypher from the cypher statement. I just need to check in Neo4j context sorry, Neo4j state, we have
result here or records. So I don't, it should work, I think. So we don't need to do this. So, and to do anything else. So just go over all
records and do the stuff. So it should be as simple as this. So I could delete a ton of code here and I just
use useReadCypher for now. I would probably also want
to get like the arrow back if I have an error and
then do something about it. But let's see, what's
interesting is the acing stuff. So useReadCypher. I don't know if I have to do
a weight sink, useReadCypher. So, and then all the other
code stays the same, I think. Okay. So let's see what happens if you run this, so this was pretty easy and simple, and I just
wanted to see that stopped us and then we run, run start. So it will be the same
simple locking form. Actually. I think I had used the ""Game of Thrones"" database in there so I need to create a
""Game of Thrones"" database. So let's see if we have
mighty database support and use Neo4j database, default database you can pass our default
database to our provider. Let's do this. So in our index JS, you can provide what's it called database
studio base "Game of Thrones". Or we can actually use movies. Or let me "Game of Thrones" and easiest way to get an get a "Game of Thrones" database in here. It's actually use system, create
database "Game of Thrones". And then I adjust, use the
graph data science playground. I hope it's the right one. Oh, it doesn't have the GDS or APOC thing which I just wanted to
install the dataset. Yeah. We could probably do a search, let's stop this playing. And then plugins, we just quickly
install these two and then we can get going. As you can see if you are
doing the three first graph one I just have to finish this. And then if this all works we can, I can push it to
GitHub and then you can use it with Neo4j, which would be really nice. So let's restart this as well. And then with Neuler we can,
many developers has started. You can do this connecting to database. It's still starting. Okay, cool. This was pretty cool because
you could delete a lot of stuff and the other things aren't all there. So the only thing that I'm not sure about that I have to ask them is kind of the whole async promise stuff. If that's something that
I, how I would do this. But otherwise I mean,
the three fourths graph is fairly simple because
it's just a very component that loads its state based on the query. And then it creates an nodes set or not nodes area, and then
links area from the nodes. And then basically this is my data. which I start out with some fake data and then basically have the query here which whenever I change the
query it changes the state. And then when I click it it does to reload and calls
three load data method here. And then I just use
force graph to the react component from the three
force graph library and pass in my graph
state, pass in some config. And that's it. Right. And then I have a
minimal neo4j browser things. So let me just import into the
"Game of Thrones" database. I want to import "Game of Thrones". Okay. Yes. Adam says we don't need async
evade for the use-neo4j. We just should take care of loading. So if it's loading then we should probably let's see if loading
set state, something like this and our state is loading false initially. And then in our vis we can say, either so what is this loading? Then we want to have, is it this? When it's loading we just say p loading. Our component here. So I hope I didn't break anything. I should have probably tested it first before the loading thing but it's probably really ugly record. So this is loaded so we
should now have Neo4j browser in our "Game of Thrones" graph. We should have the "Game
of Thrones" database. Alright. Text, season one. So we need to change this one right? Two X, one X, season, one. So it complains that, yarn start. Let's see what happens now. use-neo4j doesn't contain
any of the default export. So I probably in my index chairs, I need
to do the curly braces thing. You know, because it exports. So loading is not defined that's probably the this dot state. Okay. And see what happens, you know? Oh, I guess (indistinct). that's my index CSS,
so let's (indistinct). Index, CSS, body, app, CSS. Good question. I don't know if Adam is kind
of putting this into a summary. Oh no, that's my, I don't know. Okay. Index CSS. So does all the login form. It'd be cool. If you could just import an a use-neo4j, CSS thing,
so we don't need to copy and paste this so I let
Adam know, did I graph this? And I'm not a hundred
percent sure it would go into App CSS or index CSS actually. This is an index CSS. So it's available for the whole. Okay. This looks nice, all right. Database "Game of Thrones" different. So we need to, of course there
should be a password field So we connect to Neo4j. And does anything happen here? No, nothing happens here. This doesn't complain. Did we get anything here in console, connect to Neo4j, Neo4j,
test, "Game of Thrones", Neo. Oh, there we go. In military, I took quads. Hooks can only be quoted in the body of a function component. Okay. So that means you have
to learn some new stuff. So just this all component and we can't call it from in an method. Okay. So we need to learn what this
function component thing is that you're talking about. So here's our app
TSX, and it's a function app. If you can only call it from
within function component. So so, and then function component is something that returns stuff let's see. So this is a regular component
and we should turn this into a function component
and the function component but I don't know how the hotel stick. Let me see what, but Adam says
default functions, alphabets. Okay. If you get all
loading records loading then this then this then this. Okay. So I just type off
what he tells me to type. Let's see. So we have an export function CypherViz export default function. CypherViz is our thing here,
so we have const query I think. So you a break everything. So it's seems it
doesn't seem to be that easy. And initially I thought
it's really easy, but okay. And then we have basically
loading comma records. This, all of it saw it from separate. So this one here, so we get to
put off all the other things. And then if if loading, we
just turn basically the loading bit, and let's you return
the full component. And of course we return
should be in round parentheses if I'm not mistaken. So, and for those who
just say loading here it's probably not the right way to do it because Adam used to use this salt thing sort of loading we just
set the result to our p and otherwise the result
is our forced three graph. So that's the spit. And we would have to an old
component lifted, she bang. And I'm trying to write this myself and not just fried it
off item, but Edinburgh. Right. So, oops. This, and then this bit has to happen. Just so does this all function? Export default function service. This is our query, this is our records. And then I this bit is our data. So we don't have no data. So these are the things that
I don't know how to do it. Now, do you do unclick thing and the actually doula
component support issue? No comments. No. So I don't know how
to do the load thing. Okay. I'm gonna just save it here. And I also don't know how
to do the unchange here so that's something I need to figure out. Okay. But at least it should
render the aesthetic thing. All right. So this is our function component and in our App.js should
use this function call. So let's see if it complains something in a compile kind of dream
properties, state of undefined. I've probably in the load thing cannot read property map of undefined records map but didn't have I get records from do you use
suite, I thought actually the useReadCypher returns
a eager results state which has query result which has records. That's interesting. so we should see our query and
these should be our records. So let's see about Adam
wrote as well, and then okay. As if records, okay. As if error, should probably
do some error handling right. So that's usually for
facade equals error, okay. Perhaps it's just decipher
error or something like that. Error is not defined, oh we should get the error back here as well. Okay. And I'll be good to thing. And you provide a value prop to fulfilled without an unchanged load. That's a warning. Okay. If we get our query back but it seems you don't
get any results back. So let me just quickly
run this in the browser. So that the data model is correct Yeah. So this returns stuff in a browser, but I
don't get records back. But we saw that the
result should have records And then each records is a record at least what I think it is. So if you do a console.look,
loading of the court records, proper JavaScript
debugging by my colleagues. So we have it's loading, loading loading, and here it's
records is actually empty. That's interesting. So why is records empty if you changed this
query to something else? Match n return id of n,
limit n, let's see, oh sorry. Not that query, but just query, so what does it complain about? Here are records? So it, could it be that it connects to the wrong database somehow, that it
doesn't use this database somehow that I provided it "Game of Thrones". That's weird. Okay. So what you're going to do then is so the default database
is just a movie's graph. Right. But if you are sneaky,
we can just steal this stuff and run it in a movie graph
just to get the data in. What? Oh, copy pep, smart,
copying, not copyable. Think that's an instrument
to people to make stuff not copyable. Oh, we have Neo4j not being hurtful for constraints and not
be getting to data in. Okay. So it could be in
principle or in theory that it's, I'm not expecting
to database correctly. Okay. So if I moved to and this
is done, so we have to data and default database and waiting to reload and let's see, just now returns still no records. So I'm not a hundred percent sure why it does not turn any records. I do this query again,
console and not name. This stuff should be done. Right. So, no, it's even
in a movie database. Okay. Adam said I could also use
two databases parameter here "Game of Thrones". Okay. Let's try this. So okay. All records are no. Yep. So just seems to have helped. So let me just go back
and connect to this. Ah, there we go. So that seems to be a multi database issue in Neo4j. So the other thing that Adam wrote to me is kind of the state handling for the query we can do
in a functional component. Use state. So useState, import
useState from react, cool. And do you want to have let
or const, query, setQuery, this equal to useState of what's the thing or default query. And that'd be quote, set query and down. I think I couldn't do this. Let's see. So we just pass this to use state, which is our default value said very so. So that took care of state handling, setQuery, so the question is
do I have to use here query or is it, I think it's const and then I need to use unchange setQuery. A target value. Oops. So, and the reload thing is, I don't know then Metro would be
probably automatic whenever. So this should be interesting
because then when I type so that's something that you don't quite I don't want to go on, but
anyway, so what happened here? Line 38? setQuery, each
target value doesn't exist. So I try value, value
doesn't exist either. Can we just pass in setQuery as a target? Query expected to us be a
string, but was undefined. So the question is query now a function,
if it comes from state or is it an, query's not a
function, what else is it? Query, setQuery. I think this whole Jack talk since data is something that
I need to read up on it. So anything that Adam says, let's see, useReadCypher square brackets on useState. Okay. That's thank you. I missed it. I thought it was just a regular thing. It's some JavaScript magic, I guess. So let's try this again. Cool. I never changed something. It should probably be render,
not Heinlein using anymore. Object, object, object, object setQuery, target value, is not defined. So it sets the whole event on this. Hmm. Good question. So this works but then
it sets the whole event which is of course not what I want. Right. For change anything here you enter sets the event and then
it doesn't do anything. Okay. So I forgot that this is a function here
and then we say new target. It would be nicely to get
some out of the box stuff. In fact, for stuff like this. if I just post function, I
just want to have to way video. So kind of nice. Okay. Target. Okay. Cool. So just seems to work. So we'd need to fix the reload button of course, and kind of don't move it here but this is all like no,
a functional component. We don't have an, we don't
have an class anymore. And it uses hooks both for state handling and for Neo4j actions. So I'm bleeding edge. I think of last year. I think last summer react
hooks were introduced as well. So I need to figure out the reload button and then
I can, I can push it to get up again because I actually
don't want to tweet load on typing in the field. I just want to basically update the state. So I probably have to
add an indirection here that then triggers something when the button is pressed or so. Alright, well, I don't know something. Okay. But you could delete a bunch of code and you don't need to about
managing neo4j anymore. So we couldn't move out
console locks as well. And this is basic now
or our error handling, what actually wanted is if you put an error in here let's say this, shouldn't it return an error from the use-neo4j? If loading else if records, else if error. So if you move, move outs, else if error up here, because I would
think there should be an error if I break the else if statement, right. That's bad. So that doesn't seem to be an error here. Okay. First one defines of a break. The else if statement
does not return an error. So it's probably, it's
something in use-neo4j if you need to see you
what's happening here. So the other trick you wanted
to show you, I don't even know if it still works is this
one is called graphic charts and I've wanted to use
this to demonstrate the use of Victoria formidable labs,
Victoria chart components. And this is even worse
because it's even older I think from the driver's perspective. So I wanted to see if I
get this updated as well and all the things that I know now it should be super fast,
as you can imagine. Right? So yarn at use-neo4j then you can
probably remove the driver. As such, we import neo4jProvider from use-neo4j. And then you just provide
our app with a neo4jProvider. And we don't need to driver here anymore. So all just driver management goes away which is really nice. Don't need a driver anymore. And I'm actually not sure about, you can just do service work. I hope it's something we don't
need anymore in the future. So where's our appJS? Oh, it's just a default. So, and we want to use import readCypher from use-neo4j. I think that what's (indistinct). Why can't I remember this function name? Use-readCypher, okay. I guess it's the naming convention for the hooks. From use-neo4j and search term, query,
driver, state and so on. So our app has to become
an function component. And what do we have a
state name and people. Okay. And the search term is name. Okay. If you also need a use state. So export default function app you have a function component. Now we don't have a construct anymore but you want to use const name comma, set, name is state, use state of all and
const people, setpeople. Is useState and an empty array. So this is all state. So, and then it's a set
search term function. Do we actually need this anymore? So we just need to have const loading records is use, oops this touchpad is really annoying, useReadCypher of query and then basically I'm not a hundred percent sure how this set name would now work. So we set up people, our
result records and so on map. So, and then I had return and we have our two components,
a search term function, which I don't know if I have to make to, I guess, state or something like that. Oops. And our name property passed to this and then sure
people was missing to here. So basically what you do is basically we have a filter name named people set people, if you update a
state here and it said search to in function is passed into
this person's edge component which is then come on just
taking that and displaying it. And if it's changed and it's
just quotes said search terms. So hopefully we don't
need to change this one. So if I run this, yeah I probably push it to get up
in the second branch first. So until I fixed the load button so let me do this while
does this loading push the other one to a separate
branch so you can do it. Git status. Git, git commit. Changing Neo4 interactions
to git branch react-hooks to use Neo4j. Okay, cool. So it should be now on GitHub if you go to the hooks branch. So cool. If you have pull requests feel free to send a pull request. I'd be perfectly happy to take them. So graphed demo charts is empty right now. So something is not working yet. Okay. Graphic demo charts. It doesn't like start scripts. Compiling, does it complain about. Search term is not defined result is not defined and set
search term is not defined. Okay. What do I do? I did. I think I just close this
one so I don't get confused. Okay. Our App.js, we have
a function of component. It has name and set name,
people and set people. So, so the question is set search term. It doesn't use this as function. Why doesn't it use this as a function? End result is not defined, where's result? Ah here, result, records, okay. Actually, I don't know if this works, if the non well,
this is not really helpful. Yarn just dying on me. Come on. Can do it. So Adam says he will
do is Lazy ReadCypher, allows you to define running after you crack to back
pattern, for example. Okay. That's something that I can use for outside of the set
search term, button. So I have my person search,
which is this component and it has a button and unclear good court
set title and said title calls this prop sets approach
to a move to state where you that's probably something
that you can always get in line, I guess. And right. So it just should be, you
know, you can also leave it. So I'm going to do this and
it gets the title passed in. And you said search term. So I want to leave this actually like it is I didn't name his name. So name is wife's name
and not title, title. So I pass name as a property here, but I
don't use name anywhere here. And I think it's an old pack. I think I stole it from
some in a champion. So props or title as to
value or just it valuable. And if I call this then
it calls this, okay. But yarn still dies on me. Why does it, no such file or directory. I'm not sure what it wants from me. Okay. What else do we have? Yeah. So TB base. Yeah. I said at the beginning you might
have become a little bit late. So this is really meant
to be, as Adam pointed out in the repository,
this is meant to build meant to be used for no,
as you point out, sorry should probably you pointed
out on the repository as well. It's meant for prototypes,
graph apps, demos, proof of concept apps so
we don't have a server API or sort of let you talk to them. I'm not sure why yarn is dying on me here. It says in the script
start it has no steampath. Why does it need steam path? I don't know what is this? I can create a steam path. There's a steampath. It goes to steam, no
such file or directory. But I don't know why
it's looking for that. Anyway. I think we're out of time. I just want to show you
where you find the other app. Is in Neo4j dev tools, graph-app-charts, oh, I should have showed this before. So the idea was to use a movie graph and then show a bunch of chart components and a bunch of card components
and stuff like that. So I kind of just wanted to play around for react back then and yeah. So I'll try to make this work with Adam and push the update here as well. So it's been already quite some time ago so I thought it was due
for an update as well. So I still hoped it was useful seeing me struggle a little
bit with these things and I think if you found one or two issues with
use-neo4j that we can fix.