I am using enzyme 3.9.0.
I have just refactored a class component to a component that uses the useState hook.
I was previously testing the component's internal state by extracting it like this:
const shortcutActions = wrapper.state().shortcuts;
expect(shortcutActions).toHaveLength(1);
Is it possible to query the internal state when useState is used?
Hooks are brand new and Enzyme is being updated to support them.
You can follow the general progress here: Issue #2011.
Support for useState in particular is being tracked here: Issue #2008.
So the current level of support for useState is:
mount supports get and rendered element update with set
shallow supports get, but does not yet support rendered element update with set
As for querying the internal state directly, I'm not sure that is necessary.
From this section:
Hooks don’t work inside classes. But you can use them instead of writing classes.
...so hooks only work in what React prefers to now call "function components".
Any state defined using useState will exist only inside the function body and will not be accessible to anything outside the function.
The only way to modify that state is by interacting with the rendered output that the function returns, so testing a function component should just involve interacting with the rendered component and verifying that it re-renders as expected.
Related
In a Todo app made with React, like this one, we have a function toggleTaskCompleted in the App component which gets passed as a prop to each Todo component. This function can then be called in the Todo component when a button is clicked resp. a checkbox is toggled.
I wonder if we can move this logic entirely to the Todo component. For example, this is possible in Svelte and Vue. In Vue, we create a ref for the list (and in Svelte, a regular variable), loop through it to list all todos and pass the respective todo as a prop. When we change the todo in the Todo component (for example, mark it as complete), this change is automatically also seen by the parent App component. (Meanwhile, the approach by passing a function as a prop is also possible in Svelte and Vue.)
I prefer this approach much more, it is more encapsulated, and we have to write less code. So I wonder if we can do the same in React.
Edit. Actually, the list is updated in the App component. However, this does not effect a rerender, and also useEffect, depending on the list, won't notice this change. So my question is basically how to inform the component about this change (without writing too much code or even using external state mangement).
I guess it would be better to use React Context in this case because you'll need to applay the state and the logic for your Todos in many components (like a navbar to track number of todos ...) . In this case React Context is a way to manage state globally. So it allow your components to access some global data (In your case your todos and the function toggleTaskCompleted ) and and re-render when that global data is changed . this is a simple Demo how to use it
I read the docs about useEffect and understand how it makes life more easier than life cycle methods. Yet I am wondering what would not be possible without useEffect?
E.g. instead of (all code is dummy code)
useEffect(networkRequest.then(update state));
couldn't I just use
// inside functional component
function App() {
networkRequest.then(update state)
}
What do you mean "makes life more easier than lifecycle methods"? React hooks are how you utilize component lifecycle in functional components.
Just like the render lifecycle method of class-based components is to be a pure function without side-effects, so to is the entire body of a functional component. The body of a functional component is the "render" function.
// inside functional component
function App() {
networkRequest.then(update state)
}
The above, as written, has no guard protecting the side-effect of the network request nor state update... it will simply update state and rerender, and update state and rerender, ... ad nauseam, or in other words, infinitely render loop.
React hooks are what allow you to utilize component lifecycle in functional components.
To directly answer your question though:
Yet I am wondering what would not be possible without useEffect?
It would not be possible to trigger side-effects such as any asynchronous network requests, authentication, etc... It wouldn't be possible to invoke any specific when a component mounts or rerenders. It wouldn't be possible to run any specific logic when a specific state/prop value updated.
Now I'm on changing class based component into functional component, and there's instances which I should determine to use useRef or useState.
I already tried to get my answers using stackoverflow Q&As, it keeps me wondering.
What I understood is useRef and useState keeps value during whole apps, and useState cause rerendering and useRef is not.
we needs rerendering process if there's some changes in view, If so, Should we create whole variables with useRef which is not in return( <> ...</>)> ?
Generally Ref is used when you dont want to component re-render again but you want value in some form so that you can use later. In layman term if you just want to play with dom related stuff like updating width, height etc.
Common example for using ref:
When you want to focus in and out your input without using state(as you dont want to render the component again)
Updating dynamically style(Fox ex: You create your accordian then you want to update heigh and show transition when according open and close(if you dont want to show you can avoid this example))
If you want to create this type of utilities then you dont need to play with states you can do only with ref
for most use cases you want to handle your react component's behavior through state provided from useState (or props where you get as parameter). that's the React way to go.
eventually there will be cases to useRef, where you may need for example to access a DOM element directly for some special reason. but they are exception cases. if you you see yourself calling useRef throughout your application you are most likely doing something wrong.
I've just created a function component which contains the expression const [state, setState] = useState(). Now that I have access to state and setState(), this stateful function component is very similar to a stateful class component. I'm only aware of two differences between this component and a typical class component: when referring to the state we must use state.handle instead of this.state.handle, and we have easy access to the Context API outside of the render method.
Aside from the differences that I found already, is there any difference between this stateful function component and a stateful class component? Am I incorrect in my above assertion?
To refine this question just a bit, is there anything a Class Component can do that a Function Component with Hooks can't do?
Before The Hooks:
There was a clear separation between Stateful and Stateless
Components.
You use write Classes when you want your component to have some
state, and you use the Function components when you think your
component won’t require any state.
After Hooks:
With the introduction of Hooks, we can create stateful components without using classes.
We can use functions to create stateful components.
Helpful Articles
Article 1
Article 2
As Sung M. Kim said there are 3 life-cycle hooks that is not implemented yet in react hooks.
getDerivedStateFromProps
As mentioned in the docs, getDerivedStateFromProps exists for
only one purpose. It enables a component to update its internal state
as the result of changes in props.
You can achieve the same using useEffect & useState hooks.
useEffect accept as a second parameter an array of dependent variables to that will cause the useEffect to rerun, so you can do the following:
const [state1, changeState1] = useState(props.prop1);
useEffect(() => {
changeState1(props.prop1)
}, [props.prop1]);
componentDidCatch
getDerivedStateFromError
This hooks catch errors in the children tree except the following (docs):
Event handlers (learn more) Asynchronous code (e.g. setTimeout or
requestAnimationFrame callbacks) Server side rendering Errors thrown
in the error boundary itself (rather than its children)
There are a lot of differences between a function and a class, and they show up in the syntax. Furthermore, lifecycle methods in component classes are different than hooks in component functions. But the bottom line is that you aren’t missing any functionality by using function components. In fact function components with hooks are now the default way to create react components. Lots more here:
https://reactjs.org/docs/hooks-intro.html
I don't feel right to store a function in a reactjs state, but not sure any disadvantage? Could anyone help analyze it?
view1: function() {
return <div>view1</view>
}
view2: fucntion() {
return <div>view2</view>
}
goView1: function() {
this.setState({contentView: view1})
}
goView2: function() {
this.setState({contentView: view2})
}
render: function () {
return(
{this.state.contentView()}
)
}
There're a few common gotchas about state in react:
Don't mutate state directly, use setState instead
Don't use state when not referenced in render, use instance variable instead.
Well, it seems fine to use state as function, since it's used in your render function to return what to render? Alright, it might not be an anti-pattern, but a better place to put those functions might be in your props, aka render prop, a few reasons:
Think state as your component's data model.
Data are not stale, it changes over time, it could be results from async operations, ui states after user interactions, controlled forms values etc.
Just like redux stores your app's global state, react state should store your component's local state that changes over time, while functions most of time, does nothing more than deferring execution.
Render props is different, it offers IoC (Inversion of Control) for free.
Props most of time similar to local state, should be concerned with UI rendering. However, unlike state owned/managed by component itself, props are passed from parents/clients of the component.
Event handlers for example, event target (usually DOM elements like button, input etc) doesn't need to know how to handle events when creating the component, instead it yields control back to component client/consumer who might need to use setState in its handleEventName handler to update certain container's state shared across children.
Some library (e.g., react router4) also shifted from HOC to render props (e.g., react 16.3 new context API - provider/consumer pair) in favor of its flexibility and explicitness. Instead of composing HOCs before runtime for static version of final enhanced component, you can declare what to render using render props and composing them at runtime in render functions. Thus, you get a clear separation between data (state/props) provider and consumer (where render props are passed from).
Regarding any performance (re-render) concerns, i think it's totally fine to use state as function, since most performance tricks are done by using shouldComponentUpdate hook with shallow compare state/props references (e.g. React.PureComponent, Redux Connect etc), so it's where immutability and memoization comes into play.