Cornerstone Tools do not work (after following doc) - javascript

first of all,please be patient with this post, because this is my first question here on the platform.
Currently I'm trying to display some .dcm images using Cornerstone. This has worked and looks good.
But since a few days I have the problem that I can't get a simple tool from Cornerstone tools to work with it.
My goal was to start with the wwwc-tool and then the stack-scrolling.
I worked strictly after documentation, but it is simply not possible for me to include any tool. I just don't see the error and don't get any error output.
Can you help me with that?
import React, { useState, useEffect, useRef } from "react";
import { makeStyles } from "#material-ui/core/styles";
import cornerstone from "cornerstone-core";
import cornerstoneMath from "cornerstone-math";
import cornerstoneTools from "cornerstone-tools";
import Hammer from "hammerjs";
cornerstoneTools.external.cornerstone = cornerstone;
cornerstoneTools.external.Hammer = Hammer;
cornerstoneTools.external.cornerstoneMath = cornerstoneMath;
cornerstoneTools.init();
export default function Dummy() {
const dicomRef = useRef();
const imageIds = [
"wadouri:http://127.0.0.1:8080/api/challenges/1/series/1/images/1",
"wadouri:http://127.0.0.1:8080/api/challenges/1/series/2/images/1",
"wadouri:http://127.0.0.1:8080/api/challenges/1/series/3/images/1",
];
// define the stack
const stack = {
currentImageIdIndex: 0,
imageIds,
};
// Add our tool, and set it's mode
const { LengthTool } = cornerstoneTools;
useEffect(() => {
// Enable the DOM Element for use with Cornerstone
const element = document.getElementById("navbar");
cornerstone.enable(element);
cornerstone.loadImage(`${imageIds[0]}`).then((image) => {
cornerstone.displayImage(element, image);
cornerstoneTools.addTool(LengthTool);
cornerstoneTools.addToolForElement(element, LengthTool);
cornerstoneTools.setToolActive(LengthTool.name, { mouseButtonMask: 1 });
});
}, []);
return <div ref={dicomRef}>aaa</div>;
}
My dependencys are as follow:
"dependencies": {
"#material-ui/core": "^4.9.14",
"#material-ui/icons": "^4.9.1",
"bootstrap": "^4.5.0",
"cornerstone-core": "^2.2.4",
"cornerstone-math": "^0.1.6",
"cornerstone-tools": "^3.19.3",
"cornerstone-wado-image-loader": "^3.1.1",
"daikon": "^1.2.42",
"dicom-parser": "^1.8.5",
"hammerjs": "^2.0.8",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-lottie-light": "^1.2.5",
"react-scripts": "3.4.1"},
I just want to display the Viewer with the tools in returning div.

Can you try changing useEffect() to:
useEffect(() => {
// Enable the DOM Element for use with Cornerstone
const element = document.getElementById("navbar");
cornerstone.enable(element);
cornerstone.loadImage(`${imageIds[0]}`).then((image) => {
const viewport = cornerstone.getDefaultViewportForImage(element, image);
cornerstone.displayImage(element, image, viewport);
const LengthTool = cornerstoneTools.LengthTool;
cornerstoneTools.addTool(LengthTool)
cornerstoneTools.setToolActive('Length', { mouseButtonMask: 1 })
});
}, []);

Related

The difference between the two export ways when use observer from react-mobx?

the demo url : https://github.com/allSmi/cra-app
"mobx": "^6.6.1",
"mobx-react": "^7.5.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
bad
const App = function () {
// toggle comments this line and save, the console will log error
// const [test, setTest] = useState(0);
return (
<div>...</div>
)
}
export default observer(App);
the first way, when add or delete the hooks, after save, the console will log error
error info image
Warning: React has detected a change in the order of Hooks called by App. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks
Uncaught Error: Rendered more hooks than during the previous render.
good
const App = observer(function () {
// toggle comments this line and save, isOk
// const [test, setTest] = useState(0);
return (
<div>...</div>
)
})
export default App;
What is the difference between the two ways?

React LeafletJs Map doesn't re-render even on state change? [duplicate]

I'm a new leaflet user for my Typescript and Hook based React application. In my app my current geolocation position(latitude, longitude) is taken(I've allowed the permission to the browser) using the chrome browser's geolocation API by the app and should be shown in the map with a marker. The issue is, the map is always displayed with the initial default position([0,0]). That is, the new position update taken from geolocation API is not displayed.
The issue might be simple but I couldn't understand what I'm missing here that the Leaflet map is not taking my updated position. I checked, new position values are printed correctly, even I rendered just the updated position values inside a simple div, the new values are rendered correctly. Here is my code as below. Any help is much appreciated.
App.tsx
import React from 'react';
import './App.css';
import { Container } from '#material-ui/core';
import {Route,Switch} from 'react-router-dom';
import Header from './components/Header';
import SideBar from './components/SideBar';
import ShowInGoogleMap from './components/ShowInGoogleMap';
import ShowInLeafletMap from './components/ShowInLeafletMap';
function App() {
return (
<div className="app-div">
<Header/>
<div className="main-content">
<SideBar/>
<div className="map-content">
<Switch>
<Route path="/google-map" component={ShowInGoogleMap}/>
<Route path="/leaflet-map" component={ShowInLeafletMap}/>
</Switch>
</div>
</div>
</div>
);
}
export default App;
###############################
ShowInLeafletMap.tsx - this is the function handling Leaflet map
import { LatLngExpression } from 'leaflet';
import React, { useState, useEffect } from 'react';
import 'leaflet/dist/leaflet.css';
import { MapContainer, Marker, Popup, TileLayer } from 'react-leaflet';
const ShowInLeafletMap = () => {
const [position, setPosition] = useState<LatLngExpression>([0,0]);
useEffect(() => {
if ("geolocation" in navigator) {
console.log("Available...");
navigator.geolocation.getCurrentPosition(function(cPosition) {
console.log("Latitude is :", cPosition.coords.latitude);
console.log("Longitude is :", cPosition.coords.longitude);
setPosition([cPosition.coords.latitude,cPosition.coords.longitude]);
});
} else {
console.log("Not Available");
}
}, []);
console.log('this is loaded, ', position);
return(
<MapContainer center={position} zoom={13} scrollWheelZoom={false}>
<TileLayer
attribution='© OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<Marker position={position}>
<Popup>
Hi I just found Dresden
</Popup>
</Marker>
</MapContainer>
)
}
export default ShowInLeafletMap;
Here is dependency block of my package.json. I've no dev dependecies for the time being.
"dependencies": {
"#material-ui/core": "^4.11.4",
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.1.0",
"#testing-library/user-event": "^12.1.10",
"#types/googlemaps": "^3.43.3",
"#types/jest": "^26.0.15",
"#types/node": "^12.0.0",
"#types/react": "^17.0.0",
"#types/react-dom": "^17.0.0",
"#types/react-leaflet": "^2.8.1",
"#types/react-router-dom": "^5.1.7",
"leaflet": "^1.7.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-leaflet": "^3.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"typescript": "^4.1.2",
"web-vitals": "^1.0.1"
},
In react-leaflet version 3, most props are immutable. As for the MapContainer itself:
Except for its children, MapContainer props are immutable: changing them after they have been set a first time will have no effect on the Map instance or its container.
You're better off using the whenCreated prop to capture a reference to the underlying L.map instance in a state variable, then using leaflet methods directly:
const ShowInLeafletMap = () => {
const [map, setMap] = useState<L.Map>()
useEffect(() => {
if ("geolocation" in navigator && map) {
navigator.geolocation.getCurrentPosition(function(cPosition) {
map.panTo([cPosition.coords.latitude,cPosition.coords.longitude]);
});
}
}, [map])
return (
<MapContainer whenCreated(setMap)>
...
</MapContainer>
)
}
Working codesandbox
In leaflet v.4 I used this anti-pattern to rerender (wondering about their documentation):
<MapContainer key={new Date().getTime()} ...>

No get query sting data in react

I'm trying to get query string parameters tho, it's blank.
This is URL.
https://master.deeiswmgeowge.amplifyapp.com/?site=gfg&subject=react
Then, this.props is empty.
The below is the source.
import React, { Component } from "react";
// Importing Module
import queryString from 'query-string'
class App extends Component {
state = {
site: 'unknown',
subject: 'i dont know'
}
handleQueryString = () => {
// Parsing the query string
// Using parse method
console.log(`this.props`, this.props)
let queries = queryString.parse(this.props.location.search)
console.log(queries)
this.setState(queries)
}
render() {
return (
<div style={{ margin: 200 }}>
<p> WebSite: {this.state.site} </p>
<p> Subject: {this.state.subject} </p>
<button
onClick={this.handleQueryString}
className='btn btn-primary'>
click me
</button>
</div>
);
}
}
export default App;
"dependencies": {
"#testing-library/jest-dom": "^5.11.4",
"#testing-library/react": "^11.1.0",
"#testing-library/user-event": "^12.1.10",
"query-string": "^6.14.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.2",
"web-vitals": "^1.0.1"
},
This is the error image.
You're not using react router , thus no location parameter in props :
so you have two solution ,
1 whether adding react-router-dom and wrap your app with router , ( or using with router hook like export default withRouter(App))
2 or access directly window.location.search and get params with URLSearchParams
by example :
const urlParams = new URLSearchParams(window.location.search);
const site = urlParams.get('site');
const subject = urlParams.get('subject');
Need to pass the props like
onClick={()=> this.handleQueryString(this.props)}
and received like
handleQueryString(arg) {
....
}

Invalid hook call when trying to render a component after a Redux state change in jQuery project

I want to remove jQuery gradually from my project in favor of React. I'm trying to use functional hooks to update the view after the Redux state changes. I coded up a working example on codepen.io. However, when I try to do this in my project, I get an invalid hook call error when trying to use a functional component. I seem to somehow have 2 versions of React, but I'm not sure why. Would this be caused by a webpack misconfiguration? Commenting out the call to useSelector in my comment supresses the error.
The console returns false for this check.
console.log(window.React1 === window.React2);
npm ls react
-- react#16.13.1
//package.json
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.1",
//.babelrc for babel 7
// Invalid hook call error persists if modules & targets are commented out and the defaults are used instead
"presets": [
[
"#babel/preset-env",
{
//turn off transpile to CommonJS
"modules": false,
//allow native async await
"targets": {
"node": "10"
}
}
],
"#babel/preset-react", //parse jsx syntax
]
}
//webpack.config.js
//rules
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
//MyUl.jsx
import React from 'react';
import { useSelector } from 'react-redux';
window.React2 = React;
console.log(window.React1 === window.React2);
let liKey = 0
let li = (count) => {
return <li key={liKey++}>{count}</li>;
};
let buildList = (count) => {
let list = [];
for (let i = count; i--;) {
list.push(li(count));
}
return list;
};
export const MyUl = () => {
const blockList = useSelector(state => state.blockList);
let count = 4;
return (
<ul id='list'>
<li>1st element</li>
{buildList(count)}
</ul>
);
};
//main.js
import React from 'react';
import { MyUl } from './MyUl';
ReactDOM.render(MyUl(), $('#blockLinks')[0]);
window.React1 = React;
It turns out I was missing the Provider component when I was rendering. "Invalid hook call" is a terrible description for this specific error.
//main.js
import { Provider } from 'react-redux';
ReactDOM.render(
<Provider store={store}>
MyUl
<MyUl/>
</Provider>,
$('#blockLinks')[0]
);

How to simulate an event on a unit test with Jest, Enzyme for React-Native

I'm trying to figure out how to test an "onPress" event with Jest in a React-Native app so I can make sure the right function is called.
I went through the documentation and Google but couldn't find a solution for it in React-Native.
This is what I found that is supposed to work for React-Native with enzyme:
const mockFunc = jest.fn();
const component = mount(<MyComponent onPress={mockFunc} />);
component.simulate('press');
expect(mockFunc).toHaveBeenCalled();
But this doesn't work. Seems like mount doesn't work and I get this output:
ReferenceError: document is not defined
I tried with shallow instead but the TouchableOpacity is not getting rendered when I look at the output of the function... and you've guessed it, it doesn't work either. Not sure what to do.
Does anyone found a way to test events on React-Native?
Thanks
Enzyme does not support React-Native, because it's rendered differently and doesn't use the DOM. That's why you're getting the error ReferenceError: document is not defined. You can see this issue for more information. The React team is currently working to expose a .find() method in react-test-renderer to simulate actions on components. Then it should work for both React/React-native without needing a DOM environment.
There's a hack you can do (and that's what we did in our company) that is rendering a custom component that extends TouchableOpacity and map onClick to call onPress. Something like this:
const mockPressable = (name) => {
const RealComponent = require.requireActual(name);
class Component extends RealComponent {
render() {
return React.createElement(
RealComponent.displayName || RealComponent.name,
{ ...this.props, onClick: this.props.onPress },
this.props.children
);
}
}
return Component;
};
jest.mock('TouchableOpacity', () => mockPressable('TouchableOpacity'));
And in your test code, you call component.simulate('click').
It's a hack and I'm not sure what are the consequences of doing this but it has worked for our use cases.
You should use shallow instead, then called .dive()
const mockFunc = jest.fn();
const component = shallow(<MyComponent onPress={mockFunc} />);
component.dive().simulate('press');
expect(mockFunc).toHaveBeenCalled();
I'm able to run tests like what you've described in your question in React Native. Here is my configuration:
package.json
"scripts": {
...
"test": "node_modules/jest/bin/jest.js",
}
"devDependencies": {
...
"enzyme": "^3.1.0",
"enzyme-adapter-react-16": "^1.0.1",
"enzyme-to-json": "^3.1.2",
"jest": "^21.2.1",
"jest-enzyme": "^4.0.0",
"jest-expo": "~21.0.0",
}
"jest": {
"preset": "jest-expo",
"setupFiles": [
"./test/jestSetup.js"
],
"snapshotSerializers": [
"./node_modules/enzyme-to-json/serializer"
]
}
test/jestSetup.js
import { configure, shallow, render, mount } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
configure( { adapter: new Adapter() } )
// enzyme
global.shallow = shallow
global.render = render
global.mount = mount
Example component:
import React from 'react'
import { Button } from 'react-native'
const CancelButton = ( props ) =>
<Button
{ ...props }
onPress={ () => { props.navigation.goBack() } }
title="Cancel"
/>
export { CancelButton }
Example test
import React from 'react'
import { CancelButton } from '../CancelButton'
test( 'onPress', () => {
const goBackFunc = jest.fn()
const navigation = {
goBack: goBackFunc,
}
const component = shallow(
<CancelButton
navigation={ navigation }
/>
)
component.simulate( 'press' )
expect( goBackFunc ).toHaveBeenCalled()
} )
.babelrc
{
"presets": ["babel-preset-expo"],
"env": {
"development": {
"plugins": ["transform-react-jsx-source"]
}
}
}

Categories

Resources