I have a child component called ZimModel.vue where I created a method drawGrid(). I need to call this method in parent component (mainPage.vue). The idea is to call this method once the user has finished typing values in input (namely: width of the grid - I added #input event to v-model="inputWidth"). That's why I also use setTimeout with 5 sec delay. However, I have no idea how to 'send' this method up to parent component. I tried with emit but I don't think it makes any sense.
I use Vuex store in my app but this particular method is strictly related to other data and methods in ZimModel.vue so I don't think it' makes sense to move it to Vuex. Is there any pattern/good practice I should follow in this case?
Here is a reproducible example: https://codesandbox.io/s/vue-2-playground-vuex-drag-and-snap-to-tiles-un6984?file=/src/components/mainPage.vue.
As an example I added myGreeting() method (in mainPage.vue) to show how I want my program to work. I need to replace this exemplary method with target drawGrid() method.
Using $ref will solve your issue:
<ZimModel ref="zimModel" />
And inside your method:
triggerDrawing() {
clearTimeout(this.timer);
// this.timer = setTimeout(this.myGreeting, 5000);
this.$refs.zimModel.drawGrid();
}
Whilst the using ref should work, you should consider outsourcing the method to a .js and importing the method in the files you need it. This is especially recommended when using a method in several components.
In the new file:
export function drawGrid() {
// Your code
}
In your components
</template>
<script>
import { drawGrid } from 'relativePath'
// using {} you can import a single function or few select to improve effectiveness
...
Then you can just call the function.
Related
I've been working with react for years and I still have a simple question that I could never understand nor get the answer anywhere. Is calling an outside function in react component body bad?
For example:
import { getUser } from './helpers';
function MyComponent() {
const user = getUser();
return (
...
What will happen to user variable when component gets re-rendered by the parent component? Variables created in component body are created again in memory? Should I use useCallback or useMemo? I feel those two react functions are for other reasons, as expensive calculations and to prevent unecessary prop re-render.
To answer your first question in my experience I've never heard of calling outside functions within a react body as bad. In fact it's always been something that was encouraged especially for helper functions like in your example. There are definitely other ways to handle helper functions that may be needed multiple times (useContext comes to mind) but I don't see anything wrong with importing an outside function to call within a react body.
As far as what happens to user in your example it would get reset to the new return of getUser() upon any component re-render.
The user variable will be set to the value returned by getUser() on each re-render. And yet, getUser() will run on each re-render.
React Hooks are functions with use at the beginning of the function name, documented here.
I've been working on react native for the last 3 months, but i have no experience when it comes to building a website in just react. I would like to know if its possible to re-render the "index.js" file, after a certain function in a different file is called? I want to know if maybe i can do this through a useState variable, lets say "firstTimeLoading", that only calls that function when its true and then that said function changes that variables state to false, so that way that function is only called once. Is it possible to use this method? Is it the best choice here? And how do i pass that varaible to another file so i can change its state?
Ooh thats a tricky one, i'm not that great at redux but i think redux could solve that problem. However some tricks i used which aren't great is by emitting functions that change the state in the parent. In that way does the parent rerender and the childrens rerenders aswell.
function changeName() {
setState({name: "test"});
}
render(){
return(
<Child emitter={this.changeName} />
)
}
this way does the child call changeName with the help of props and the parent later calls its function since the function "changeName" is in the props to the child.
if you want to update the whole site could you simply use this terrible call:
window.location.reload();
Is it a good practice to do this in ReactJS?
var Component = React.createClass({
render: function () {
return (<div></div>);
},
field: 'value', // is this safe?
method: function () {
// do something with field
}
})
Before starting to suggest that I should use this.props or this.state, for me it's not the case, because those are fields that do not affect rendering in any way directly, they just work together to control the rendering.
I would like to use the React class as I do with regular javascript 'classes'.
My main concern here is how those fields and methods are handled inside React, and if the fields are set on the instance itself or directly on the prototype, which would not be suitable at all for what I need.
I ran a quick test and it seems that the fields are set on the instance, and the methods on the prototype, which is ideal. But is this the expected and documented behavior? And is this safe for future versions?
I think it can work the way you are doing and that it's safe. However if I understand well you are proceeding data calculation/transformation directly in the view.
So I would advise that you remove this logic from the view and treat it in the model part of a mvc or mv*, in your backbone models, or in your flux store for example.
This way you won't be mixing data transformation logic and pure rendering.
I would say so, I have been using things like this for a while and have not seen any issues. For example, let's say you want a handler of some sort that you want to pass to nested components, you would create the function in this component and pass it as a prop to a child. I believe they have examples that use similar concept in the ReactJS Facebook site.
Under the hood React is just looping through the properties of the object you pass to createClass and copying them to the prototype of the Component. Primitive values like strings or numbers obviously cannot be copied by reference, so don't get shared across all instances, whereas objects, functions, arrays and so on will.
If you want to work with values that are just local to the component instance you need to use the state API. I'm not sure what you mean by "[state and props] do not affect rendering in any way directly, they just work together to control the rendering". The whole point of props and state is that they work together to generate values to be used when (re)rendering.
https://facebook.github.io/react/docs/component-api.html
A React component should only render in response to either changing props or changing state. You cannot/shouldn't trigger a re-render by mutating other fields directly.
You need to think of your component as something closer to a pure function. State and props go in at the top, and static VDOM/HTML comes out.
I would re-write your example as,
var Component = React.createClass({
getInitialState: function () {
return {field: 'value'};
},
render: function () {
var field = this.state.field;
return (<div>{field}</div>);
},
method: function () {
var field = this.state.field;
// do something with field
this.setState({field: 'anotherValue'});
}
})
I'm using Sinon to spy on the method, but the method I'm spying doesn't seem to be called at all when I try to Simulate onSubmit on the form tag.
Here's a JSFiddle.
First of all, this line:
React.addons.TestUtils.Simulate.submit(Instance, form.getDOMNode());
Should be:
React.addons.TestUtils.Simulate.submit(form.getDOMNode());
But that doesn't solve the problem, because of the way your component is structured. You're already giving the current _handleSubmit function to React to call, and React will invoke that function. It won't call Instance._handleSubmit(), which is the one you've replaced. If you change your component to something like:
var that = this;
...
<form onSubmit={function() { that._handleSubmit()}}>
It works because you explicitly call the method on the instance.
But I would advice you to not assert that the method was called, but instead assert that whatever side effect it should perform was actually performed. Like mutating state, calling an external service, etc.
I am trying to combine Angular and React.js. I have an work example project here I have seen a couple of ways to bring the Angular and React.js together. One of the methods I have seen is to create a directive and create the React component in the link function. For example in the first part of the project to generate the React version(in red) I am using
.directive('reactElementRepeater', function() {
return {
link: function(scope, element) {
var update_react = function(oldVal, newVal){ //Called every time one of the two values change
React.renderComponent(Demo_Element({
numberOfElements: scope.myModel.numberOfElem,
numberInElements: scope.myModel.numberInElem
}), element[0]);
}
scope.$watch('myModel.numberOfElem.length', update_react);
scope.$watch('myModel.numberInElem', update_react);
}
}
});
What I want and what should happen in a React enabled application is for something in the model to be updated, then that update is sent through React and it will alter the DOM as little as possible to reflect that change. It looks like that instead of updating a bit of the DOM this will Create a new React component each time with renderComponent.
React.renderComponent() instantiates the root component, starts the
framework, and injects the markup into a raw DOM element, provided as
the second argument.
Is it actually recreating the elements each time? If that is the case is there a way to alter this so that doesn't happen?
Just to be clear I know about ngReact, I just want to know other ways to speed up Angular with React.
Yes this is fine, it's not mounting the component multiple times.
When you call React.renderComponent() the second argument is the element which react should render the component to. So react notices if you are rendering the same component to a dom element that already contains a mounted instance of the component, and does not re-mount the entire component, it just updates the properties of it instead.
You can see this in action if you make a component with componentDidMount function defined. You'll notice that componentDidMount will only execute the first time renderComponent gets called. And afterwards, subsequent calls to renderComponent on the same target dom element will not call it because the component is already mounted. Likewise getDefaultState and getDefaultProps also only get called on the first renderComponent call.
If you're asking will the render function of the component be called every time the answer is yes. But this is how react works, you want the render function to get called because props might have changed. You can block it from being called by using shouldComponentUpdate (http://facebook.github.io/react/docs/component-specs.html#updating-shouldcomponentupdate) and returning false. However react developers recommend you don't use this to block render calls unless you have specific performance problems - most of the time it should be fine to just let the render call execute as it wont cause any slow dom updates unless things have actually changed.