Cannot assign to read only property 'props' of #<Object> in react native - javascript

Cannot assign to read only property 'props' of #
I checked #1654 with no success. Please have a look at the issue in more detail here-
Basically what I am doing is using a Navigator to move from index page to ApplistGridView page.
I see the navigation is successful(from logs) but, even before I see the screen I face this issue.
And chrome debug messages-
Code is posted at Github
Haven't found a solution.
What am I doing wrong?

You cannot push to props this.props.nav.push({id: 'Applist', index: 2}); since component properties are read-only, as the error states. Props can only be derived from a parent component, but cannot be modified.
EDIT: This article is a great starting point for people confused in this matter as I was a while ago:)
https://reactjs.org/docs/thinking-in-react.html

If this is happening to you not because of props but because of state, you may be trying to do an assignment like this:
this.state.nav = 'whatever';
Remember that assignments to state in React should be like:
this.setState({
nav: 'whatever'
});

You write this.props.nav.push({id: 'Applist', index: 2});
But this.props is read-only; you cannot modify it.
If you want to pass some value to the parent react component, then you can use this.prop.onSomeEvent(value) in a child component. Then handle the push process in the parent component.

In file node_modules\react-scripts\scripts\utils\verifyTypeScriptSetup.js
change
ts.JsxEmit.ReactJsx
to
ts.JsxEmit.ReactJSX

Just One thing:
npm install typescript#4.0.5
Restart the server

Related

React Navigation (5+) navigation.addListener() in Class Components

I want to add a Listener beforeRemove to a navigation to prevent the user from going back.
Then they get an alert to proceed or discard.
I followed the tutorial from reactnaviagtion.org but this is in an functional Component.
In my Case its an react-native Class-Component.
I can easily call the function over the props:
componentDidMount(){
this.props.navigation.addListener("beforeRemove", (e) =>{
console.log("beforeRemoveTriggered");
this.state.SomeVariablesToCheckIfGameStarted
Alert.alert(..., onPress: ()=> this.props.navigation.dispatch(e.data.action));
}
}
The console.log is no problem but I can't call the state inside of the callback.
beforeRemoveTriggered
But after that I get the following error:
TypeError: undefined is not an object (evaluating '_this2.props.someVariablesToCheckIfGameStarted`)
- node_modules\...
My Guess is that you cant call the state inside of the listener-callback.
But this is neccessary for the app function so i cant "just dont use the state".
BTW a workaround with useEffect would be accetable but is not preferred.
This may have a simple solution which is not specific with react-navigation or react-native but javascript.
Any tips would be helpful, thanks in advance!!!
I know my answer...
Maybe but just maybe I called this.props instead of this.state
And maybe after this discovery everything works as it should be...
I`m sorry to everyone I bothered figuring out what the solution is!

Unable to retrieve TinyMCE's content from a parent component

I have asked the question on their Github but no answer so far so I'm trying my luck here.
I'm creating a form that contains TinyMCE as component ; my goal is to be able to use and reuse this component through the whole website as the main Wysiwyg. I import it, give it a v-model and I'm good to go.
So, it "works", as in, I can set a value via the v-model and TinyMCE will display it nicely. However, it looks like I'm on a write only mode, because I can't extract the current data from it.
I originally created an example for the Github issue, you can see it here so that you have a good idea of what I'm facing. There's a textarea under the TinyMCE component that has the same v-model, just try to play with it and see the behavior.
While everything works if I declare a v-model inside the TinyMCE component, what do I need to do
get my value to the parent component?
Thanks in advance
You need to use v-model on the editor itself too or else it only receives the parent value but can't update it. However, you can't use the prop value for that because props can't be mutated.
Using a computed setter with v-model is a good solution here:
<editor
api-key="qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc"
v-model="model"
></editor>
Leave the value prop as is and add the computed:
computed: {
model: {
get() {
return this.value;
},
set(val) {
this.$emit('input', val);
}
}
}
The computed setter returns the prop when getting, but emits rather than setting it.

How to enable tracking deep changes in component props

I have a component who initialized like this
<custom :opts="{map: false}"></custom>
and there is HTML similar to this
<template id="custom">
<div v-if="opts.map">
I'm awesome
</div>
<button v-on:click="show"></button>
</template>
where
function show(){
this.opts = {map:true} // (1) <-- This is working and I could see hidden div
this.opts.map = true // (2) <-- For some reason not working
Vue.set(this.opts, 'map', true) // (3) <-- Still not working
}
So my question is why variant 2 doesn't work and what should I change to make my control react to value reset on a button click. Or a proper explanation why (1) is working, but (2) isn't - also will be accepted as an answer.
The real problem with the code (all 3 versions) is changing a component's property from within a component. In idiomatic Vue, only the parent should change properties. If a component needs to effect a change, it should emit an event to the parent and let the parent make the necessary changes. Otherwise, there is ambiguity in which component "owns" the property.
One Way Data Flow
All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around.
Sending Messages to Parents with Events
Can be off base here but I believe this happens because in vue component props are not reactive, so their objects are not being observed in depth. Or rather they are "a little bit reactive", reassigning the root prop does cause the DOM update but is not expected to be done manually and you'll see a warning when doing such on development build:
[Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "..."
And for as why props are not completely reactive in the first place: https://v2.vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow
To work around the whole issue you must pass any necessary props to the component data and if those props were passed as nested objects you might also want to completely avoid mutating them from within the component since it will propagate to the parent which, unless clearly mentioned, can be a source of bad news.

VueJS Error on sharing data from one component to other

I'm getting some errors in my VueJS application. IMG - http://prntscr.com/exh499
I understand that error exist because country property doesn't exist before I load data from weather JSON, but what is the way to remove this error. Also above [Vue warn]:
This is the GitHub repo, there is a bit more code so I'm not sure if you can read it here.
https://github.com/DenisLapi/weather-app
Also how to look for changes of some property in Component 2 if I edit that property in Component 1 (I'm usign $emit) but when I define property value in Component 2 and then edit that property in Component 1, usign $emit and props[] seems like value is not updated in Component 2
[Vue warn]: Error in render function : (found in <SearchResult> at C:\Users\denis\Desktop\weatherapp\src\components\Result.vue)
TypeError: Cannot read property 'country' of undefined
citydata.foo is undefined, which is fine, but citydata.foo.bar is an error since you're trying to get bar off undefined.
You should wrap everything using citydata with a v-if since it's async.
<div v-if="citydata">
<!-- Now you can use `citydata` safely. -->
</div>
Edited: fiddle with a working example https://jsfiddle.net/wostex/63t082p2/24/
BTW, there is no 'country' property in JSON output: example
You can
set default values for your props: https://v2.vuejs.org/v2/guide/components.html#Prop-Validation
check properties presence before using them in templates (v-if on content blocks)
About reaction on props change: use computed property which depends on prop value, or even watch prop changes: https://v2.vuejs.org/v2/guide/computed.html#Watchers (it depends on your needs)

this.refs.something returns "undefined"

I have an element with a ref that is defined and ends up getting rendered into the page :
<div ref="russian" ...>
...
</div>
I want to access the DOM element properties like offset... or something. However, I keep getting undefined and I haven't the faintest idea why. After some searching it's clear that refs are only applicable to one file but I'm not using this anywhere besides this one page. I'm saying this to log it:
console.log('REFS', this.refs.russian);
What could be causing this?
Check that you are not accessing ref before the child component has been mounted. E.g. it doesn't work in componentWillMount. A different pattern which auto invokes ref related callback after the element has been mounted is this-
<div ref={(elem)=>(console.log(elem))}/>
You can use this notation to get mounted elements in deep nesting as well -
<div ref={this.props.onMounted}/>
The correct place to work with refs is inside specific React lifecycle methods e.g. ComponentDidMount, ComponentDidUpdate
You cannot reference refs from the render() method. Read more about the cautions of working with refs here.
If you move your console.log('REFS', this.refs.russian); call to ComponentDidMount or ComponentDidUpdate lifecycle methods (assuming you are on React >= 14) you should not get undefined as a result.
UPDATE: also refs will not work on stateless components per the caution link above
Update since React version 16.4
In your constructor method define your ref like this
constructor(props) {
super(props);
this.russian = React.createRef();
}
In your render where you are using ref do this.
<input
name="russian"
ref={this.russian} // Proper way to assign ref in react ver 16.4
/>
For e.g if you want to have focus when component mounts do this
componentDidMount() {
console.log(this.russian);
this.russian.current.focus();
}
Reference Refs Documentation React
I was having a similar issue in my form validation methods, trying to assign this.ref.current.reportValidity()
Writing the method I was doing this in as validate = () => {} instead of validate() {} helped me out, but I'm not totally sure why exactly, just something I remembered from habits I had in my past work experience that gave me this. Hope it helps and could someone kindly clarify this answer with why this might work exactly.
If you are exporting class withStyle, please remove and export default nomally.
Instead of putting your Console.log inside the function example(){...} you should put it inside:
example=()=>{....}

Categories