Moving variables from one file to the other in React JS - reactjs

I'm a noob with React JS and I'm trying to understand how to export a variable from a file and import it into another. What I tried is this:
File App.js:
import React from 'react'
function App() {
[hi, setUpHi] = useState('Hello World')
return (
<div className='App'>
<Test />
</div>
);
}
export default App
export {hi}
File Test.js:
import React from 'react'
import {hi} from './App'
function Test() {
return (
<div>
{hi}
</div>
)
}
export default Test
But this doesn't work :(
It says that hi is not defined. I tried to define it outside of the function, this also doesn't work. Can anybody help me?
ps:
I know that I could do it easier by using props:
<Test hi = {'Hello World'} />
and then
function Test({hi}) ... \\ etc.
But with this example, I want to understand how to export and import variables, which might be much easier than passing props. (Or am I wrong with this assumption?)

Looks like you are trying to reference the "hi" variable outside of it's function scope (it's declared in the component, not at root level) - hence why it's undefined in the global scope.
Also, FYI it's an antipattern to use component state in this way. State is internal to the FunctionComponent App and exposing it's state in this way could compromise component purity.
If your intention is to share state between components, either pass them through props, or use a custom hook.

Related

Calling Stitches createStitches for every component in React

I'm using Stitches to write my CSS in a React application, mainly for the theming and variables. I'm calling createStitches in every component file, like so:
ComponentA.tsx
import { createStitches, styled } from "#stitches/react";
const { createTheme } = createStitches({ theme: {...} });
...
export default ComponentA;
ComponentB.tsx
import { createStitches, styled } from "#stitches/react";
const { createTheme } = createStitches({ theme: {...} });
...
export default ComponentB;
And then I'm importing these components and using them in App.tsx:
import ComponentA from "./components/ComponentA";
import ComponentB from "./components/ComponentB";
function App() {
return (
<div className='App'>
<ComponentA />
<ComponentB />
</div>
)
}
I know I can just call the createStitches in the App.tsx file once, but I like keeping my components self-sufficient, as in they should work without any other extra work. Is this a bad approach, or is this something that is fine to do? Does React call the function many times, or just once? Thanks for any help!
You do not need to call createStitches for every component. This function is to create configuration for your application styling. I don't that you are going to have separate configuration for every component.
This will just cause extra work. Just keep the createStitches in a common file and import it from there

Why am I getting error “hook cannot be called inside a callback” when setting state in React?

I am new to React, and I am trying to integrate React hooks in some of the projects that the React course I follow uses. This example is supposed to add an input field which sets the background color of a page. When I load the page, after 1 second, I get the following error
src\App.js
Line 16:43: React Hook "useBackgroundColor" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks
Search for the keywords to learn more about each error.
What might be the issue here? I haven't managed to figure it out.
Thank you!
import logo from "./logo.svg";
import "./App.css";
import UserItem from "./UserItem";
import React, { useState } from "react";
function App() {
const [backgroundColor, useBackgroundColor] = useState("purple");
return (
<div className="App" style={{ background: backgroundColor }}>
<h1>Lista utilziatori:</h1>
<input type="color" onChange={event => useBackgroundColor(event.target.value)} />
</div>
);
}
export default App;
Functions prefixed with use are interpreted by React to be hooks. But here, your useBackgroundColor isn't actually a hook, it's just a state setter function. Rename it to something more appropriate - the usual convention is to prefix the state variable with set. Change
const [backgroundColor, useBackgroundColor] = useState("purple");
to
const [backgroundColor, setBackgroundColor] = useState("purple");
and then reference setBackgroundColor in your code.

createContext hook not working for react components inside JSP

I am rendering my react component inside an existing JSP page using
ReactDOM.render(
React.createElement(MyReactComponents.myReactComponent, {
props
}),
document.querySelector("#id")
);
and the react component is as follows:
import MyStore from "./MyStore";
const MyReactComponent: React.FC<any> = (props: any) => {
const store = useContext(MyStore);
store.myFunction();
---code---
}
and MyStore is as follows:
export class MyStore{
---Code---
}
export default createContext(new MyStore());
But i'm getting this error:
And one more importing thing to notice is that when I'm trying to render this react component on top of another existing react component, i'm not getting any error and everything is working fine.
Can someone please explain me what might be causing the issue?
I'm not sure, but maybe you are misusing the useContext hook?
Whenever you use it inside a component Child, then at least one of its parent component must call the <Context>.Provider, so that it is initialized down the tree.
In your example, you render MyReactComponent using ReactDOM.render: due this, I suppose MyReactComponent is the first component in your tree. If that is the case, when you use useContext inside it, it cannot find any MyStore context.
So, probably, you just need to wrap your MyReactComponent with a context provider.
export class MyStore { ... }
export const MyStoreContext = createContext(new MyStore());
---
ReactDOM.render(
<MyStoreContext.Provider>
<MyReactComponent {...props />
</MyStoreContext.Provider>
, document.querySelector("#id"));
And then, inside MyReactComponent, you can use const store = useContext(MyStoreContext);.

Please explain this abbreviated ES6 JSX declaration

An example in the SurviveJS handbook in the chapter on React and Webpack has me confused.
In Note.jsx:
import React from 'react';
export default () => <div>Learn Webpack</div>;
This deviates in a number of ways from what appears to be the standard way of declaring React components using JSX:
import React from 'react';
class Note extends React.Component {
render() {
return <div>Learn Webpack</div>;
}
}
How does the first example work?
How does it know the component is called Note so that it can be referred to as <Note/> in some parent component? Simply by filename match (removing the .jsx part?)
Where's the render() function? And how is it possible to omit it?
What are the limitations of this approach? I am guessing that it only works for wrapping a very simple rendered output, just mapping properties into some HTML...
Where is this style documented? I can't seem to find any official documentation
It doesn't, when you do <Note /> that is just looking for a variable named Note in the local scope. When the component is imported into another file, you can name it whatever you want. e.g. import Note from './Note'; would import the default-exported function in your example.
This is a stateless function component, https://facebook.github.io/react/docs/reusable-components.html#stateless-functions, as you linked to yourself. The function itself is the render, it has no class instance.
They can store no state since they just take inputs and render outputs.
Your specific example is just an arrow function. The documentation linked above uses standard non-arrow functions, but they are essentially interchangable in this case. e.g.
export default () => <div>Learn Webpack</div>;
is the same as
export default function(){
return <div>Learn Webpack</div>;
}

How to render a reactjs component stored in a redux reducer?

I have a redux reducer loaded with several reactjs components.
I want to load these inside other components through this.props
Like: this.props.components.MyReactComponent
class OtherComponent extends Component {
render() {
const Component = this.props.components.MyReactComponent
return (
<div>
<Component />
</div>
)
}
}
Is this possible? If so, how?
EDIT The component is a connected component. I am able to load it but it is broken. In this case, it is a counter, when you click to increment or decrement nothing happens. In the console, there is this error:
Uncaught ReferenceError: _classCallCheck is not defined
if I convert the component into a dumb component (without connecting it), the error is this:
Uncaught ReferenceError: _classCallCheck3 is not defined
EDIT 2
I found out why those errors show up. It is because the react component gets stripped out when stored in the reducer:
A react component would look something like this:
{ function:
{ [Function: Connect]
displayName: 'Connect(Counter)',
WrappedComponent: { [Function: Counter] propTypes: [Object] },
contextTypes: { store: [Object] },
propTypes: { store: [Object] } } }
However, after I store it inside a reducer, it loses its properties and ends up looking something like this:
{ function:
{ [Function: Connect] } }
After reading the comments below, I thought of an alternative. I can store in a reducer the path to each component, then make a new wrapper component that could render those other components from those paths.
I tried it but encoutered a different problem with the funcion require from nodejs that for some weird reason is not letting me user a variable as an argument. For example:
This works:
var SomeContent = require('../extensions/myContent/containers')
This does not:
var testpath = '../extensions/myContent/containers'
var SomeContent = require(testpath)
Giving me the following error:
Uncaught Error: Cannot find module '../extensions/myContent/containers'.
It is adding a period at the end of the path. How can I prevent require to add that period?
If you can think of any other alternative I can implement for what I am trying to do, I would greatly appreciate it.
EDIT 3 Following Thomas advice...
What I am trying to accomplish is this:
I want to be able to render react components inside other react components, I know how to do it the same way most us know how to; however, I want to be able to do it by importing a file that would contain all the components without actually having to import and export each one of them:
OtherComponent.js
import React, { Component } from 'react'
import { SomeComponent } from '../allComponentes/index.js'
export default class OtherComponent extends Component {
render() {
return (
<SomeComponent />
)
}
}
SomeComponent.js
import React, { Component } from 'react'
export default class SomeComponent extends Component {
render() {
return (
<div>
Hello
</div>
)
}
}
allComponents/index.js
import SomeComponent from '../allComponents/SomeComponent/index.js'
export { SomeComponent }
What I am trying to do in allComponents/index.js is to avoid having import/export statements for each component by reading (with fs module) all the components inside the allComponents folder and export them.
allComponents/index.js (pseudocode)
get all folders inside allComponents folder
loop through each folder and require the components
store each component inside an object
export object
When I tried that, I encountered multiple issues, for one, export statements have to be in the top-level, and second, fs would work only on the server side.
So, that is why I thought of loading all the components in a reducer and then pass them as props. But as I found out, they got stripped out when stored them in a reducer.
Then, I thought of only storing the path to those components inside a reducer and have a wrapper component that would use that path to require the needed component. This method almost worked out but the nodejs function require wont allow me to pass a variable as an argument (as shown in EDIT 2)
I think your question is not really to do with redux but rather is (as you say):
What I am trying to do in allComponents/index.js is to avoid having import/export statements for each component by reading (with fs module) all the components inside the allComponents folder and export them.
By way of example, I have all of my (dumb) form components in a folder path components/form-components and the index.js looks something like:
export FieldSet from './FieldSet'
export Input from './Input'
export Label from './Label'
export Submit from './Submit'
export Select from './Select'
export Textarea from './Textarea'
Then when I want to import a component elsewhere, it is import { FieldSet, Label, Input, Submit } from '../../components/form-components/';

Resources