Unable to view Model with OBJLoader React Three Fiber - javascript

I'm trying to render an .obj file into my react project using the OBJLoader and useLoader() hook from React Three Fiber, but I'm unable to do so. My file path is correct and I'm wrapping the Model in Suspense tags, so why is this occurring?
import React, { Suspense } from "react";
import * as THREE from "three";
import { Canvas, useLoader } from "#react-three/fiber";
import { OrbitControls } from "#react-three/drei";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
function Model() {
const model = useLoader(
OBJLoader,
"../assets/Model.obj"
);
return <primitive object={model} scale={0.4} />;
}
function App() {
return (
<div className="App">
<Canvas>
<OrbitControls
enablePan={true}
enableZoom={true}
enableRotate={true}
addEventListener={undefined}
hasEventListener={undefined}
removeEventListener={undefined}
dispatchEvent={undefined}
/>
<Lights />
<Suspense fallback={null}>
<Model />
</Suspense>
</Canvas>
</div>
);
}
export default App;

You have to put your 3D files inside the public folder.
Then your path will be "./Model.obj"
Also you can make make folders inside public folder and put 3D models inside them.
ex- "./folder1/Model.obj" like this

Related

Attempting to load a .obj and .mtl file in my react app

I am currently trying to load a 3D model I made into my react app. The 3D model exported as a folder which had a model.obj and a model.mtl file. After surfing the web for a bit I figured I could use Three-JS for this. My website is currently not displaying anything on the page I have this on.
import React from "react";
import { Canvas } from "#react-three/fiber";
import { ObjectLoader } from "three";
import { useLoader } from "#react-three/fiber";
import { MaterialLoader } from "three";
const ThreeDFloorPlan = () => {
const materials = useLoader(MaterialLoader, "../models/floorplan.mtl")
const object = useLoader(ObjectLoader, "../models/floorplan.obj", loader => {
materials.preload()
loader.setMaterials(materials)
})
return (
<Canvas>
<primitive object={object} />
</Canvas>
)
}
export default ThreeDFloorPlan;
import React from 'react';
import Button from '#mui/material/Button';
import { NavLink } from 'react-router-dom';
import ThreeDFloorPlan from '../components/ThreeDFloorPlan';
const Entry = () => {
return (
<div>
<ThreeDFloorPlan />
</div>
);
};
export default Entry;
Would love some feedback or help on this matter!
I have tried various different ThreeJS walk throughs, scoured the internet, and pulled out a bit of hair.

Add 3D model in React

I want to add a 3D avatar in my portfolio built with React. I followed this tutorial: React portfolio
In my header section, I want to replace my image with 3D avatar using three.js following this tutorial
Here is the Model.jsx file
import React, { useRef } from "react";
import { Canvas, extend, useThree, useFrame } from "react-three-fiber";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
extend({ OrbitControls });
function Model() {
const Controls = () => {
const controls = useRef();
const { camera, gl } = useThree();
useFrame(() => {
controls.current.update();
});
return (
<orbitControls
ref={controls}
autoRotate
args={[camera, gl.domElement]}
></orbitControls>
);
};
return (
<div>
<Canvas>
<mesh>
<Controls />
<boxBufferGeometry
attach="geometry"
args={[1, 1, 1]}
></boxBufferGeometry>
<meshBasicMaterial
wireframe
attach="material"
color="white"
></meshBasicMaterial>
</mesh>
</Canvas>
</div>
);
}
export default Model;
Here is my Header.jsx file
import React from 'react'
import './header.css'
import CTA from './CTA'
// import Me from '../../assets/me.jpg'
import HeaderSocials from './HeaderSocials'
import Model from './Model'
const Header = () => {
return (
<header id='header'>
<div className="container header_container">
<h5>
Hello I'm
</h5>
<h1>John Smith</h1>
<h5 className="text-light"> Full-stack Developer</h5>
<CTA />
<HeaderSocials />
{/* <div className="me">
<img src={Me} alt="" />
</div> */}
<Model />
Scroll Down
</div>
</header>
)
}
export default Header
I'm getting this error message:
Failed to compile.
Module not found: Error: Can't resolve 'react-three-fiber' in 'C:\Users\xxxxx\Desktop\Projects\react-portfolio\src\components\header'
ERROR in ./src/components/header/Model.jsx 5:0-71
Module not found: Error: Can't resolve 'react-three-fiber' in 'C:\Users\xxxxx\Desktop\Projects\react-portfolio\src\components\header'
webpack compiled with 1 error
Can anyone guide me on how to do it?
react-three-fiber is deprecated, you want to use #react-three/fiber instead and so you'd do npm install #react-three/fiber or yarn install #react-three/fiber. Then you'd have to update your imports like:
import { Canvas, extend, useThree, useFrame } from "#react-three/fiber";
Furthermore, if you want to use OrbitControls, the #react-three/drei package has them built in as a JSX element, simply import it and do <OrbitControls />, more information in their GitHub page.
One last advice is that you should wrap your Model inside a <Suspense> tag, this is new in React 18 so make sure your react and react-dom packages are up to date and in-sync.

Why can't you have two AppRegistry.registerComponent lines?

I'm teaching myself React-Native and I came across this strange roadblock. Inside my App.js I'm trying to export a class and then use another file within my App.js which is inside the somePage() function. where I'm calling <Header/> in an attempt for that text to appear on my physical device upon hitting refresh.
It displays <Login/> perfectly, but not what's within the somePage() function. My question is, why?
(I'm using Expo by the way, instead of having an index.ios.js file it's an App.js file that still supports cross platform development).
Here's my App.js file:
import React, { Component } from 'react';
import {AppRegistry} from 'react-native';
import Login from './components/Login';
import Header from './components/Header';
export default class Project extends Component {
render() {
return (
<Login/>
);
}
}
const somePage = () => (
<Header/>
);
AppRegistry.registerComponent('someProject', () => Project);
AppRegistry.registerComponent('someProject', () => somePage);
Here's my Header.js file:
import React from 'react';
import {Text} from 'react-native';
const Header = () => {
return <Text>Testing this out</Text>
}
export default Header;
The concept of react is that a parent component renders child components. You only need to register once because the root component is the parent component of all other components. Any other child or grandchild components you want to render must be descendants of the root component. As a side note, you don't need to have export default in front of the Project component, because you aren't exporting it anywhere: you are registering it below.
To fix your app, you need to place the header component inside the registered root component:
import React, { Component } from 'react';
import {AppRegistry, View } from 'react-native';
import Login from './components/Login';
import Header from './components/Header';
class Project extends Component {
render() {
return (
<View>
<Header/>
<Login/>
</View>
);
}
}
AppRegistry.registerComponent('someProject', () => Project);

Additional component in <MuiThemeProvider /> results in blank page w/ no error messages

I have recently installed Material UI into my Meteor application using npm install --save material ui
I have gotten the <Header /> component showing up in my app.js file, but whenever I add other components, localhost:3000 simply displays a blank page. Please see my code below:
header.js
import React, { Component } from 'react';
import AppBar from 'material-ui/AppBar';
class Header extends Component {
render() {
return(
<AppBar
title="Header"
titleStyle={{textAlign: "center"}}
showMenuIconButton={false}
/>
);
}
}
export default Header;
app.js
import React from 'react';
import ReactDOM from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Header from './components/header';
import NewPost from './components/new_post';
const App = () => {
return (
<MuiThemeProvider>
<Header />
</MuiThemeProvider>
);
};
Meteor.startup(() => {
ReactDOM.render(<App />, document.querySelector('.render-target'));
});
THE ABOVE CODE WORKS WELL (see screenshot below)
However, if I add another component I get a blank screen
header.js is the same
new_post.js
import React, { Component } from 'react';
import TextField from 'material-ui/TextField';
class NewPost extends Component {
render() {
return (
<TextField
hintText="Full width"
fullWidth={true}
/>
);
}
}
export default NewPost;
app.js
import React from 'react';
import ReactDOM from 'react-dom';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import Header from './components/header';
import NewPost from './components/new_post';
const App = () => {
return (
<MuiThemeProvider>
<Header />
<NewPost />
</MuiThemeProvider>
);
};
Meteor.startup(() => {
ReactDOM.render(<App />, document.querySelector('.render-target'));
});
The result is simply a blank screen
Why does adding one more component (<NewPost />)inside of <MuiThemeProvider> result in a blank screen? I referred to the material-ui documentation and their sample projects but their application structure is not similar to mine. Any advice? Please let me know if you need more info to make this question clearer.
Wow very strange but I managed to get it working by simply adding a <div>
app.js
const App = () => {
return (
<MuiThemeProvider muiTheme={getMuiTheme()}>
<div>
<Header />
<NewPost />
</div>
</MuiThemeProvider>
);
}
Meteor.startup(() => {
ReactDOM.render(<App />, document.querySelector('.render-target'));
});
I would really appreciate if anyone could explain why adding a div makes this all work. Thank you!
I would really appreciate if anyone could explain why adding a div
makes this all work
If you look at the browser warning, "Invalid prop children of type array supplied to MuiThemeProvider, expected a single ReactElement.".
So, when you add a <div/> around your components, it wraps them together and turns them into a single react element.
MuiThemeProvider renders as null so you have to wrap children do anything - for example React.Fragment

Alt "connectToStores" deprecated in React/Flux App?

I am building a small chat app with React and Flux via a tutorial, however the tutorial seems to be out of date as it is using a method from Alt (used with Flux) that throws the following error:
Cannot resolve module 'alt/utils/connectToStores'
...which I believe is coming from the line with #connectToStores. Below is my code. I looked into this issue and it seems like Alt was broken up into smaller packages, one of them being Alt-React (which is stumping me completely). My question is, how can I use this method in an up-to-date manner?
import React from 'react';
import mui from 'material-ui';
import MessageList from './MessageList.jsx';
import MessageBox from './MessageBox.jsx';
import Login from './Login.jsx';
import ChannelList from './ChannelList.jsx';
import connectToStores from 'alt/utils/connectToStores';
import ChatStore from '../stores/ChatStore';
// Material UI
import * as Colors from 'material-ui/lib/styles/colors';
import AppBar from 'material-ui/lib/app-bar';
import getMuiTheme from 'material-ui/lib/styles/getMuiTheme';
#connectToStores // es7 decorator with deprecated 'connectToStores'
class App extends React.Component {
constructor() {
super();
}
static getStores() {
return [ChatStore];
}
static getPropsFromStores() {
return ChatStore.getState();
}
static childContextTypes = {
muiTheme: React.PropTypes.object
}
getChildContext() {
return {
muiTheme: getMuiTheme({
primary1Color: Colors.blue500,
primary2Color: Colors.blue700,
primary3Color: Colors.blue100,
accent1Color: Colors.pink400
})
};
}
render() {
var view = <Login />;
if (this.props.user) {
view = (
<div>
<div id="content-container">
<ChannelList />
<MessageList />
</div>
<MessageBox />
</div>
);
}
return (
<div>
<AppBar title="Chat App"/>
{{view}}
</div>
);
}
}
export default App;
The Alt Utils libraries have all been moved into a separate package at https://github.com/altjs/utils
Once installed
npm i --save-dev alt-utils
You can access the same libraries as the tutorial requires using:
import connectToStores from 'alt-utils/lib/connectToStores';
import {decorate, bind, datasource} from 'alt-utils/lib/decorators';

Categories