I can't Pass custom props to "export default" - javascript

Sorry for the noob question, i'm completely new to this, so here it goes:
I'm practicing react and normally when i do something like:
var Person = function(props){
return(
<h1>Hi, {props.name}</h1>
);
}
ReactDOM.render(
<Person name="Jon"/>,
document.getElementById("app")
);
i would see: "Hi, Jon"
but the thing is, i'm now using create-react-app and there instead of ReactDOM.render(), i just have:
export default Person;
and i don't know how to inject my props into "Person" in order to see "Hi, Jon"
i tried guessing solutions like:
export default Person(name:'Jon');
or things like that but of course it doesn't work.
I dont have enough information to google the right question even though i tried a lot of possibilities but couldn't find any solution. so i hope someone would help/educate me here.
Thanks a lot in advance!

If you have different components you must use in parrent component:
import Person from './Person';
ReactDOM.render(<Person name="Jon"/>, document.getElementById('main'));
and in child it must be smth like this:
import React, { Component } from 'react';
class Person extends Component {
constructor(props) {
super(props);
};
render() {
return(
<h1>Hi, {props.name}</h1>
);
}
export default Person;

you can pass by this way i don't know its correct but it worked for me
const test = {
myValue(props){
return props.yourValue
}
}

Related

React components with predefined prop value like html tags

I want to add values to my components prop that intellisense can recognize that and show it, so I can select them easily and not having any typo.
I'm also using react#18 and JS. functional components.
<button type="values that intellisense would show" />
<MyCustomButton type="values that intellisense would show" />
I've tried using JsDoc but that's not as good as html tags:
in case of having an example
I want to make my components like this.
any help would be appreciated.
You can use React Typechecking with propTypes to handle it.
forexample :
import PropTypes from 'prop-types';
class Greeting extends React.Component {
render() {
return (
<h1>Hello, {this.props.name}</h1>
);
}
}
Greeting.propTypes = {
name: PropTypes.string
};
or you can use Typescript, that's what typescript good at.
here is codesandbox example for prop checking https://codesandbox.io/s/test-tsx-forked-67765?file=/src/index.tsx

How to I get access to data from other functions in React component?

What are some of the best practices to get access to data from other functions to my React Component?
I have a very simple component as :
/* eslint-disable */
import React from 'react'
import { test } from './FunctionTest'
function Component() {
return (
<div>
<h1>This is from Component</h1>
<p>{test()}</p>
</div>
)
}
export default Component
I am importing a function called test from a file called FunctionTest. The file is as follows :
export function test() {
let a = 2
return a
}
My goal is to access the data a from which is returning from FunctionTest file, to my component.js file. Clearly, by doing <p>{test()}</p> is totally not the right way.
I would like to ask what are best practices to do this, and how does it relate to props as FunctionTest is simply a JS function and not a React Component
I have seen other answers over here, but they are much more complicated, so in case of closing this question, please make sure I am getting pointed to the right resources.
Any help would be great.
Thank you for reading!

Use react-i18next in class components with decorators and HOC

I'm trying to implement i18n in my React project which also uses Redux with the help of react-i18next.
In this project, we use class components with decorators.
Initially, I wanted to try react-i18next v10 but since it's relying on hooks and I cannot use those in class components, it's out of the question for me.
Falling back to the legacy v9, I followed the step by step guide (https://react.i18next.com/legacy-v9/step-by-step-guide) and performed the following steps :
Created the i18n.js config file with translations
Wrapped my root container with i18nextProvider
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<I18nextProvider i18n={i18n}>
<RootContainer />
</I18nextProvider>
</Router>
</Provider>,
$root,
);
Wrapped one simple component, which is a child of the RootContainer, with the withNamespaces() HOC, but with decorator syntax
#withNamespaces()
export default class SimpleComponent extends React.PureComponent {
// (... component class code ...)
}
Which is equivalent without decorators to the following :
class SimpleComponent extends React.PureComponent {
// (... component class code ...)
}
export default withNamespaces()(SimpleComponent);
I must be missing something since I get the following error during SSR :
react-i18next:: You will need pass in an i18next instance either by props, using I18nextProvider or by using i18nextReactModule. Learn more https://react.i18next.com/components/overview#getting-the-i-18-n-function-into-the-flow
0|ssr-dev | TypeError: Cannot read property 'wait' of null
0|ssr-dev | at NamespacesConsumerComponent.render (/client/node_modules/react-i18next/dist/commonjs/NamespacesConsumer.js:220:33)
Problem is, I'm no longer having this error if I remove the #withNamespaces() HOC on my component class, but then I do not have {t, i18n} in the component's props and therefore cannot translate anything.
Moreover, the given URL in the error unfortunately doesn't exist anymore.
As I understood from the documentation, the <I18nextProvider> is supposed to pass the {t, i18n} values down the component tree, which is not in my case.
I find myself stuck between not being able to use v10 (we have a lot of components and I can't just refactor them all to functional components at the moment) and not being able to make v9 work either.
I'm running out of options and could use some hindsight if you ever encountered similar issues.
Thanks in advance.
For anyone wondering, I got it working by wrapping the <RootContainer> child instead of wrapping <RootContainer> itself in the renderer method, which leaves me with something like the following :
Renderer
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<RootContainer />
</Router>
</Provider>,
$root,
);
RootContainer
import i18n from "../core/translations/i18n";
import {I18nextProvider} from "react-i18next";
#connectWithStore(mapStateToProps, mapActionsToProps)
export default class RootContainer extends React.PureComponent {
// (... class code ...)
render {
return (
<I18nextProvider i18n={i18n}>
<div>
<SimpleComponent/>
</div>
</I18nextProvider>
);
}
}
SimpleElement
import {withNamespaces} from "react-i18next";
#withNamespaces()
export default class SimpleComponent extends React.PureComponent {
// (... class code ...)
componentDidMount() {
// Successfully logging the values below
console.warn("Got i18n props?", {
t: this.props.t,
i18n: this.props.i18n,
});
}
}
The only difference being that my renderer is a function, not a component per se, whereas RootContainer is a fully-fledged React component (PureComponent, to be precise). Maybe it has to do with render chaining, not sure, but it still works as intended that way.
I managed to use the last version of react-i18next in class by doing like this :
import { withTranslation } from 'react-i18next';
class RootContainer extends React.Component {
constructor(props) {
super(props);
}
render() {
<span>{this.props.t('Home')}</span>
}
}

Cannot find module whenever I add another component to React JS

I am working through a Udemy Tutorial on React, and something here does not make sense. Whenever I try to add a new component to a .js file, I get an error stating that the component file cannot be found. Here is what I mean:
Originally, I had these 2 files:
my main.js :
console.log('Hello World!');
import React from 'react';
import ReactDOM from 'react-dom';
import Channel from './Channel';
document.addEventListener('DOMContentLoaded', function() {
ReactDOM.render(
React.createElement(Channel, Object.assign({}, this.props, {name:'Ryan'})),
document.getElementById('My-Channel')
);
});
and my Channel
import React from 'react';
class Channel extends React.Component {
onClick(){
console.log('I was clicked');
}
render(){
return(
<li onClick={this.onClick.bind(this)}>{this.props.name}</li>
)
}
}
export default Channel;
This code actually works, and displays the proper 1 item list.
However, when I try to add another component to my Channel.js file, it breaks. No matter what I put in, it seems that adding another component does not work.
Ex :
import React from 'react';
class Channel extends React.Component {
onClick(){
console.log('I was clicked');
}
render(){
return(
<li onClick={this.onClick.bind(this)}>{this.props.name}</li>
)
}
}
class ChannelList extends React.Component{
render(){
return (
<ul>
<Channel name='Hardware Support'>
</ul>
)
}
}
export default Channel;
Do I have to create a new file every time I want to create a component? I can't imagine that being the case, so what would you suggest I do?
Here is the Exact Error I am getting
Even if I add a simple dictionary to the end of the file, I get the same error. Its as if the only thing in this Channel.js file can be the channel component
Thank you in advance for your help!
Not being able to find a module is almost always a sign of a syntax error (assuming the files are in the right location). In your case, it's never hitting export because the following is a syntax error:
class ChannelList extends React.Component{
render(){
return (
<ul>
<Channel name='Hardware Support'>
</ul>
)
}
}
You're missing the closing tag!
Change <Channel name='Hardware Support'> to <Channel name='Hardware Support' />
Also it looks as though you should be doing:
export default ChannelList
and in your main file:
import ChannelList from './Channel'
ReactDOM.render(
<ChannelList />,
document.getElementById('My-Channel')
),
Credit to #jamesemanon for part of the solution, and #azium for the other.
So, of the problems that I had:
make sure to close your tags
for some reason, I had to use export default instead of just
export
I had to import ChannelList into my main.js file : import
ChannelList from './Channel';
Thank you both for your help, I hope some others can benefit from this in the future as well

React.js How to render component inside component?

I am stuck. I have several seperate components on seperate files. If I render them in main.jsx like following:
ReactDOM.render(<LandingPageBox/>, document.getElementById("page-landing"));
ReactDOM.render(<TopPlayerBox topPlayersData={topPlayersData}/>, document.getElementById("wrapper profile-data-wrapper"));
ReactDOM.render(<RecentGamesBox recentGamesData={recentGamesData}/>, document.getElementById("history wrapper"));
Everything works fine, but I wonder if it is a good practice? Maybe it is possible to do something like there would be only one ReactDom.render like:
ReactDOM.render(<LandingPageBox recentGamesData={recentGamesData} topPlayersData={topPlayersData}/>, document.getElementById("page-landing"));
I tried different kinds of variatons of LandingPageBox to somehow include those other two components, but had no luck. They sometimes rendered outside the page and so on. I thought it should look something like this:
import React from 'react';
import RecentGames from '../RecentGames/RecentGames.jsx';
import TopPlayers from '../TopPlayers/TopPlayers.jsx';
import PageTop from './PageTop.jsx';
import PageBottom from './PageBottom.jsx';
class LandingPageBox extends React.Component {
render() {
return (
<body className="page-landing">
<PageTop>
<TopPlayers topPlayersData={this.props.topPlayersData} />
</PageTop>
<PageBottom>
<RecentGames recentGamesData= {this.props.recentGamesData}/>
</PageBottom>
</body>
);
}
}
export default LandingPageBox;
But this code only renders PageTop and PageBottom, without player or game components.
So my question would be, how to set up LandingPageBox file so that TopPlayers component would render inside PageTop component and RecentGames component would render inside PageBottom component? Thank you.
In your example
return (
<body className="page-landing">
<PageTop>
<TopPlayers topPlayersData={this.props.topPlayersData} />
</PageTop>
<PageBottom>
<RecentGames recentGamesData= {this.props.recentGamesData}/>
</PageBottom>
</body>
);
React will only render the top-level custom components PageTop and PageBottom, as you already found out. The other components (TopPlayers and RecentGames) are nested within those components. What does that mean? React does not just display those nested components because it would not know how to do this. Instead, all rendering must be done by the outer components PageTop and PageBottom. React just passes the nested components to them (PageTop gets TopPlayers, PageBottom gets RecentGames) in this.props.children. Now it is up to the outer components what to do with these nested components. In your example, you would modify the PageTop and PageBottom components to use {this.props.children} to display their nested components in a suitable way.
You are right. You can use as many nested components as you want. It's one of the main concepts in react.
You can access them in this.props.children.
Do it like this:
var Parent = React.createClass({
render: function() {
return <div>{this.props.children}</div>;
}
});
ReactDOM.render(
<Parent>
<Child/>
<Child/>
</Parent>,
node
);
Read more here - https://facebook.github.io/react/docs/multiple-components.html
And here - http://buildwithreact.com/article/component-children
Here Car component is inside the another component i.e Garage components.
When Garage component in rendering Car component is also renders.
Same concept as like one function inside another function.
class Car extends React.Component {
render() {
return <h2>I am a Car!</h2>;
}
}
class Garage extends React.Component {
render() {
return (
<div>
<h1>Who lives in my Garage?</h1>
<Car />
</div>
);
}
}
ReactDOM.render(<Garage />, document.getElementById('root'));

Categories