I have a Class Component in a React App. It works. Then I need a global variable and reached to the React's Contexts. I create Context and can consume its value.
But I need to update its value, I read a lot and it seems I have to use React Hooks to update Context value. But my components are Class Components and there I cant use hooks.
My question is, If I want to use Contexts, I cant use Class Components? Right now Im learning React and encountered to Hooks many times. If hooks very important thing, This means we have to use Function Components all the times?
What I have to do? I just need to update my global variable and use its value.
If I want to use Contexts, I cant use Class Components?
No, you can use context either in Class Components.
See Context section in docs, all examples are with classes.
We have to use Function Components all the time?
No, you can use any approach you see fit.
But, there is no actual reason to use Class Components any more (except implementing Error Boundary). React officially recommends using hooks and composition, therefore the preferable approach is Function Components.
What I have to do? I just need to update my global variable and use its value.
A global variable as the name stands, its global to the application's scope (and not bound to component's scope like state). You can update it from everywhere.
const globalObject = { name: `myVar` };
// Can be updated from any scope as you keep the reference.
const FunctionComponent = () => { globalObject.name=`a`; return <></>; }
// Outer scope
globalObject.name=`b`;
Please visit this link, https://www.taniarascia.com/using-context-api-in-react/ and How to update React Context from inside a child component?.
it is explained in this link, you can do this way :
class LanguageSwitcher extends Component {
render() {
return (
<LanguageContext.Consumer>
{({ language, setLanguage }) => (
<button onClick={() => setLanguage("jp")}>
Switch Language (Current: {language})
</button>
)}
</LanguageContext.Consumer>
);
}
}
Related
From React documentation.
Conceptually, components are like JavaScript functions. They accept
arbitrary inputs (called “props”) and return React elements describing
what should appear on the screen.
Considering:
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
or
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
Will give us the ability to do this:
<Welcome name="Luke" />;
<Welcome name="Leia" />;
to use as we wish in the DOM,
Hello, Luke
Hello, Leia
Now when people prescribe props shouldn't be changed, it would make sense the reason is in my thinking would be like the same as changing the values of attributes of an image tag?
HTML:
<img id="Executor" alt="Picture of Executor" src="/somepath/vaders-star-destroyer-executor.jpg"/>
JS:
Meanwhile in a Javascript file a long time ago in a galaxy far, far away...
var imageOfVadersStarDestroyer = document.getElementById('Executor');
imageOfVadersStarDestroyer.src = "/somepath/vaders-star-destroyer-avenger.jpg"
Because if we keeping changing an elements attribute values this can cause confusion and slower renderings?
So is the reason why the prescription is to never change props in React is because is the library is trying to make elements as predictable as possible?
Setting props outside of React is dangerous and should be avoided. Why? The main reason is that it doesn't trigger re-renders. Hence bugs and unexpected behaviour.
Re-rendering
Most of the time, props are data that is store as state in the parent component, which is manipulated by calling setState() (or the second function returned by React.useState()). Once setState() is called, React re-renders and computes what has changed under the hood, with the latest props and state. Manually assigning values to props, therefore won't notify React that the data has changed and something has to be re-rendered.
The good practice
Making props read-only allows React components to be as pure as possible, which is obviously a good practice anyway even when writing plain JS. Data won't be changed unexpectedly and can only be done so by calling setState() (You might have heard of the single source of truth, which is what React is trying to leverage).
Imagine you notice something went wrong in the app and the data shown to the end user is completely different from the source, it would be a pain trying to find out where the data has been manipulated wouldn't it? :)
never change props in React
means that you should never do this.props.name = "userName" because of React's one way data binding, props are read only, to update a component's props, you should pass a function from the parent that will do that ( in the parent ) , or dispatch an action if you're using redux, a change in the props will trigger a re-render
props is a constant in this case. You will always need it in your components.
But there is a cleaner way to write it or even omit it.
Regular way with Function Expression (same as your exemple)
function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}
ES6 Object Destructing - explicit
function Welcome(props) {
const {name} = pros
return <h1>Hello, {name}</h1>;
}
ES6 Object Destructing - inplicit, cleaner way
function Welcome({name}) {
return <h1>Hello, {name}</h1>;
}
And of course, you can use the class way which requires the usage of this.props.yourAttr
However, in the new version 3 of create-react-app, changed class components to functional components. You can see this exact modification on Github here.
You can need to learn more about destructing assignment in the old and good MDN linked here or an in-depth approach both array and object destructuring here.
I'm building a <BasicForm> component that will be used to build forms inside my application. It should handle submit, validation and also should keep track of the inputs state (like touched, dirty, etc).
Therefore, it needs some functions to do all that and I've been wondering what is the best place to put those declarations (concerning code organization and performance optimization, considering React and JavaScript best practices).
I'm using React 16.8 hooks and bundling with Webpack.
So far, here's what I've got:
BasicForm.js
/* I moved those validating functions to a different file
because I thought they are helpers and not directly related
to my BasicForm functionality */
import { validateText, validatePassword, validateEmail } from './Parts/ValidationHelpers';
function BasicForm(props) {
const [inputs, setInputs] = useState({});
const [isSubmitting, setIsSubmitting] = useState(false);
// These are functions to handle these events
function onChange(event) {...}
function onBlur(event) {...}
function onFocus(event) {...}
// This function creates the initial state for each form input
function setInputInitialState(inputProps) {...}
// This functions does what it name says
function validateAllFields() {...}
// This one also
function checkValidationAndSubmit() {...}
return(
<FormContext.Provider value={{
onBlur: onBlur,
onFocus: onFocus,
onChange: onChange,
inputs: inputs,
setInputInitialState: setInputInitialState
}}>
<form onSubmit={onSubmit} method='POST' noValidate>
{props.children}
</form>
</FormContext.Provider>
);
}
My question is: as you can see, up to this point, I'm declaring all the functions that my <BasicForm> uses (onChange, onBlur, onFocus, setInputInitialState, validateAllFields, checkValidationAndSubmit) inside the body of my BasicForm React component function.
Is this the best practice? If I was using classes those functions would probably be methods of my BasicForm class. But since I changed to hooks and got rid of most classes, I always have doubts about placing auxiliar functions inside or outside my React components function's body. Is there a best practice for this?
When the auxiliar function may need some variables or state from my main function, I could always pass them as parameters when I call them (if they are declared outside).
Do I gain or lose anything if I declare them outside of my BasicForm function? Keeping in mind that this is a module that gets bundled with Webpack.
If the function does not rely on props or state, then it is best to define it outside of your component function. If it does rely on props or state, then it generally makes sense to define it inside your component function, but if you are passing the function as a prop to a child component, then you should consider using useCallback (though this generally only adds value if the child component is memoized).
When the function depends on props or state, if you move the function out of the component and pass it arguments, you will end up needing to wrap that call in another function (e.g. ()=>helperFunc(prop1, someState)) in order to pass it as a prop to a child component. If the function is large, you may still want to pull it out of the component in that manner, but that just comes down to style preferences.
For more information on useCallback, see my answer here: Trouble with simple example of React Hooks useCallback
I want to do something like:
<SomeProvider showConfirm={showConfirm}>
{props.showConfirm()
? (<confirmActionComponent />)
: (<chooseActionComponent />)}
</SomeProvider>
Inside of chooseActionComponent I want to be able to access showConfirm or another value in a deep nested child component to update some value in the parent and have confirmActionComponent show.
I know how to achieve this using class which tends to involve this and bind at some point, and I would prefer to avoid that.
Is there any way to accomplish something like this using pure functions/components instead? Would also prefer to keep this out of Redux store.
If you just want to access showConfirm, you simply can pass it to the child:
<SomeProvider showConfirm={showConfirm}>
{props.showConfirm()
? (<confirmActionComponent />)
: (<chooseActionComponent showConfirm={showConfirm} />)}
</SomeProvider>
Note following quote from React docs to inheritance:
At Facebook, we use React in thousands of components, and we haven't found any use cases where we would recommend creating component inheritance hierarchies.
Anyway, I maybe have a really really dirty hack for you...
use ref...
const Child = () =>
<div ref={(self) => {
// get ReactDOMNode on stateless component
const ReactDOMNode = self[Object.keys(self).filter((key) =>
/__reactInternalInstance/g.test(key))[0]];
// access parent props
console.dir(ReactDOMNode
._hostParent
._currentElement
._owner
._currentElement
.props);
}}></div>;
Note: that this is not recommended and I won't recommend that, too.
I would advice you to simply pass needed parent props to the child.
<SomeProvider showConfirm={showConfirm}>
{props.showConfirm()
? (<confirmActionComponent />)
: (<chooseActionComponent showConfirm={showConfirm} />)}
</SomeProvider>
And in your chooseActionComponent you can:
const chooseActionComponent = ({parentProps: {showConfirm}}) =>
<div>{showConfirm}</div>;
You do not have to use ES6 classes to create React content. If you would like to avoid having to repeatedly use bind to ensure correct scoping of methods (that use this.setState / this.props), you can revert back to using the React API helper functions (see React without ES6).
You can specifically use: React.createClass for creating React classes and HOCs. Again, just to re-iterate this: using this alternative syntax will autobind this for you.
I am studying the principles of react.
According to some reviews, some people says is better to keep your component stateless, what does it mean?
But other people says, that if you need to update your component, then you should learn how to set your state to the proper state.
I saw this.props / this.setProps and this.state / this.setState and I am confuse with that.
Something I am trying to figure is, how can I update a component by itself and not from a parent component? should I use props or state in this case?
I already read some docs about props and state, what I don't have clear, is: when to use one or another ?
Props vs. state comes down to "who owns this data?"
If data is managed by one component, but another component needs access to that data, you'd pass the data from the one component to the other component via props.
If a component manages the data itself, it should use state and setState to manage it.
So the answer to
how can I update a component by itself and not from a parent component? should I use props or state in this case?
is to use state.
Props should be considered immutable and should never be changed via mutation. setProps is only useful on a top-level component and generally should not be used at all. If a component passes another component a property, and the first component wants the second to be able to change it, it should also pass it a function property that the second component can call to ask the first component to update its state. For example:
var ComponentA = React.createClass({
getInitialState: function() {
return { count: 0 };
},
render: function() {
return <Clicker count={this.state.count} incrementCount={this.increment} />;
},
increment: function() {
this.setState({count: this.state.count + 1});
}
});
// Notice that Clicker is stateless! It's only job is to
// (1) render its `count` prop, and (2) call its
// `incrementCount` prop when the button is clicked.
var Clicker = React.createClass({
render: function() {
// clicker knows nothing about *how* to update the count
// only that it got passed a function that will do it for it
return (
<div>
Count: {this.props.count}
<button onClick={this.props.incrementCount}>+1</button>
</div>
);
}
});
(Working example: https://jsbin.com/rakate/edit?html,js,output)
For and object-oriented programming analogy, think of a class/object: state would be the properties you put on the class; the class is free to update those as it sees fit. Props would be like arguments to methods; you should never mutate arguments passed to you.
Keeping a component "stateless" means that it doesn't have any state, and all its rendering is based on its props. Of course, there has to be state somewhere or else your app won't do anything! So this guideline is basically saying to keep as many components as possible stateless, and only manage the state in as few top-level components as possible.
Keeping components stateless makes them easier to understand, reuse, and test.
See A brief interlude: props vs state in the React docs for more information.
Use state when you know the variable value is going to affect the view. This is particularly critical in react, because whenever the state variable changes there is a rerender(though this is optimized with the virtual DOM, you should minimize it if you can), but not when a prop is changed (You can force this, but not really needed).
You can use props for holding all other variables, which you think can be passed into the component during the component creation.
If you have want to make a multi-select dropdown called MyDropdown for example
state = {
show: true,
selected:[],
suggestions:this.props.suggestionArr.filter((i)=>{
return this.state.suggestions.indexOf(i)<0;
})
}
props={
eventNamespace:'mydropdown',
prefix : 'm_',
suggestionArr:[],
onItemSelect:aCallbackFn
}
As you can see, the objects in the state variable are going to affect the view some way or the other.
The objects in the props are mostly objects which should remain the same throughout the component life cycle. So these objects can be callback functions, strings used to namespace events or other holders.
So if you do want to update the component by itself, you need to have to look into how componentWillRecieveProps ,componentWillUpdate, componentDidUpdate and componentShouldUpdate works. More or less, this depends on the requirement and you can use these lifecycle methods to ensure that the rendering is within the component and not in the parent.
How do people typically approach having "global" data in a React application?
For example, say I have the following data for a user once they're logged into my app.
user: {
email: 'test#user.com',
name: 'John Doe'
}
This is data that almost any component in my app might like to know about - so it could either render in a logged in or logged out state, or perhaps display the users email address if logged in.
From my understanding, the React way of accessing this data in a child component is for a top level component to own the data, and pass it to child components using properties, for example:
<App>
<Page1/>
<Page2>
<Widget1/>
<Widget2 user={user}/>
</Page2>
</App>
But this seems unwieldy to me, as that would mean I'd have to pass the data through each composite, just to get it to the child that needed it.
Is there a React way of managing this type of data?
Note: This example is very simplified - I like to wrap intents up as composites so implementation details of entire UI features can be drastically changed as I see fit.
EDIT: I'm aware that by default, calling setState on my top level component would cause all child components to be re-rendered, and that in each child component I can render using whatever data I like (e.g. global data, not just state or props). But how are people choosing to notify only certain child components that they should be rendered?
Since I originally answered this question, it's become apparent to me that React itself doesn't support "global" data in any sense - it is truly meant to manage the UI and that's it. The data of your app needs to live somewhere else. Having said that, it does now support accessing global context data as detailed in this other answer on this page. Here's a good article by Kent Dodds on how the context api has evolved, and is now officially supported in React.
The context approach should only be used for truly global data. If your data falls into any other category, then you should do as follows:
Facebook themselves solve this problem using their own Flux library.
Mobx and Redux are similar to Flux, but seem to have more popular appeal. They do the same thing, but in a cleaner, more intuitive way.
I'm leaving my original edits to this answer below, for some history.
OLD ANSWER:
The best answer I've found for this so far are these 2 React mixins, which I haven't had a chance to try, but they sound like they'll address this problem:
https://github.com/dustingetz/react-cursor
and this similar library:
https://github.com/mquan/cortex
MAJOR NOTE: I think this is a job for Facebook's Flux, or something similar (which the above are). When the data flow gets too complex, another mechanism is required to communicate between components other than callbacks, and Flux and it's clones seem to be it....
Use the React Context Property This is specifically for passing global data sets down the chain without explicitly forwarding them. It does complicate your Component lifecycle functions though, and note the cautions offered on the page I've linked.
You can use the React Context API for passing global data down to deeply nested child components. Kent C. Dodds wrote an extensive article on it on Medium React’s ⚛️ new Context API. It'll help in getting a better understanding of how to use the API.
I think React.createContext() is perfect solution for your purpose.
React will re-render only components, that listen context changes with useContext hook.
Here is a simple snippet for your code:
export const CurrentUser = React.createContext({})
const App = () =>
{
const User = getUser() // any authorisation method
return <>
<CurrentUser.Provider value={User}>
<App>
<Page1/>
<Page2>
<Widget1/>
<Widget2/>
</Page2>
</App>
</CurrentUser.Provider>
</>
}
const Widget2 = () =>
{
const User = useContext(CurrentUser)
return <>{User?.name}</>
}
In case if you want to control re-renders directly, you can use React.memo in nested components. For example, if you need re-render component only after specific attribute change.
Also, with nesting context values, you can reach good flexibility of your app. You can pass different context values for different part of your application.
export const CurrentUser = React.createContext({})
const App = () =>
{
const User = getUser() // any authorisation method
const AnotherUser = getAnotherUser() // any authorisation method
return <>
<CurrentUser.Provider value={User}>
<App>
<Page1/>
<CurrentUser.Provider value={AnotherUser}>
<Page2>
<Widget1/>
<Widget2/>
</Page2>
</CurrentUser.Provider>
</App>
</CurrentUser.Provider>
</>
}
const Widget2 = () =>
{
const User = useContext(CurrentUser)
return <>{User?.name}</>
}
What's wrong with just passing data all the way down the component chain via rendering all children with {...restOfProps}?
render(){
const {propIKnowAbout1, propIKnowAbout2, ...restOfProps} = this.props;
return <ChildComponent foo={propIKnowAbout1} bar={propIKnowAbout2} {...restOfProps}/>
}
There is Reactn https://www.npmjs.com/package/reactn
You use this.global and this.setGlobal to get and set the global state same as you do with the local state.
To be able to do so you only need to
import React from 'reactn';