Hi,
i have a problem:
class userState {
@observable favourite = [ ];
@action
handleFavourite(credentials){
Fetcher.getFavourite(credentials).then(response => {
this.favourite = response.user.favourite ;
console.log(this.favourite) ;
})
} }
so the fetcher is a function that fetch some data and get a response (an array) and i want to store that data in an observable array and when i console log my observable array i don't get the value of the array, instead i have this on my console "Proxy {
Mobx 5 uses proxies to implement the magic. The object should behave as normal array, not sure if we can do anything about the console output ... try console.log(Mobx.toJS(this.favourite)) to inspect the array ...
@FouMez can you post a screenshot? Is this in node, or in the browser? Note that in the browser you can click the target and browse it further. Or use alteratives like console.dir
I experience similar issue with observable arrays.
Mobx version: 5.0.3
Passing observable array (nested) to lovefield library (an IndexedDB API call under the hood) results in exception.
Chrome:
object passed: Proxy聽{0: Proxy, 1: null, length: 2, Symbol(mobx administration): ObservableArrayAdministration}
exception: DOMException: Failed to execute 'put' on 'IDBObjectStore': [object Object] could not be cloned.
Firefox:
object passed: Proxy { <target>: (2) [鈥, <handler>: {鈥 }
exception: DOMException: "The object could not be cloned."
My workaround is to use mobx.toJS before passing it over to the external library.
I considered this behavior "as designed" until I encountered Mobx 5.0.0 change log:
Observable arrays are now recognized as arrays by all third party libraries, which will avoid the need to slice them.
I'm having the exact same issue.
class Store {
@persist @observable secrets = [];
@persist @observable params = [];
@persist @observable fetchingSecrets = false;
@action get = () => {
this.fetchingSecrets = true;
return Constants.Agent.get('/secrets', {}).then(action((response) => {
this.fetchingSecrets = false;
this.secrets = response.data;
this.params = response.data;
}));
}
}
````
Now, according the `console.log`, this is the content of `secrets` after the get request:
Proxy聽{0: Proxy, 1: Proxy, 2: Proxy, 3: Proxy, 4: Proxy, 5: Proxy, 6: Proxy, 7: Proxy, 8: Proxy, 9: Proxy, length: 10, Symbol(mobx administration): ObservableArrayAdministration}
I've ready that this should work fine, regardless of the long, so in my component I'm doing as follows:
```js
render() {
const { Secret } = this.props;
return (
<View style={styles.container}>
{Secret.secrets.map((secret) => {
return (
<Text key={secret.id} style={styles.secret}>{secret.message}</Text>
);
})}
</View>
);
}
}
But this is not working at all, reactjs complains about the fact that the keys should be unique, and this is because secret is not the actual object I'd normally expect to see.
@nicgutierrez please set up a sandbox reproduction and separate issue, pretty sure this is a completely different problem
@FouMez @timurgarif proxies should be undetectable, in general (you can see in your debug tools that something is a Proxy, but programmatically there is / should be no way to recognize something is a Proxy or not, so this means there is something else this library cannot handle. For example the libraries does not support having symbolic members, or non serializable classes inside the array etc. Please set up small reproductions otherwise can't say much about it.
I have the same problem. The return ends up being a proxy as follows in the image: (url)

Sandbox: https://codesandbox.io/s/v0jq7y4m10
Me too, i can use it though. Only with debugging it's a bit annoying.
@viniarruda It's as designed. The proxy acts exactly the same as normal array (while being observable obviously). It's just the way it's printed by chrome's console.
Check the output of codesandbox's console (instead of the browser console), there won't be any proxies visible:
ProductStore {items: Array[0], constructor: Object}
fetch data []
Whats the idea behind this autorun?
@action
setData(data) {
autorun(() => {
this.items = data;
});
console.log("fetch data", this.items);
}
@urugator This autorun was a test, I forgot to delete it.
What would be the best way to manipulate this proxy? Because I can not really manipulate it as a normal array.
I can not get the actual example I'm using from api because of cors, but in my application it returns an array of objects. The value of this.items ends up being a proxy and I can not handle it as I normally would with an array
I can not handle it as I normally would with an array
Can you be more specific? Does it throw some exceptions when accessing array props or invoking methods or what exactly doesn't work?
From the screen you posted earlier, it seems like your api is returning empty array ... proxy's target is the actual array, if you wanna inspect it.
Unfortunately I can not use my real api in the sandbox to show the return, despite being in the chrome the result is this:

Trying to manipulate like you would in a normal array using a map ends up not working.
It says that the map is not a function, because it is not an array.
Sorry if I was not clear at some point.
Check this: https://codesandbox.io/s/7z2l6yq1v6
Note that Proxies are non-polyfillable ES6+ feature, be sure you're testing it in environement which supports it.
I updated the sandbox.
Can not I manipulate the response array? Usually a map would solve the problem.
Here: https://codesandbox.io/s/y18q3j4rx
I think you're just mixing products/data/items ...
Sorry, but that does not make much sense to me. The response array is not observable, but the normal fields are. Do I need to turn it into an observable.array?
Are you referring to the sandbox I posted? The response array is non-observable exactly the same as if it would be coming from axios. It becames observable (and the objects within) at the moment it's assigned to observable field this.products
Yes, exactly. But the moment it turns this.products, the array inside it is not manipulable with a map in the component, just in the store. Should it be that?
No... just check the sandbox it uses .map in component to render the products
Please, look this: https://codesandbox.io/s/m5ml9vly4y
The map works in console.log, but in the view not work
I don't see any map call except in render.
Get rid of that axios call and replace it with the actual result.
Also you can even remove that @observable, fix the code and then slap @observable there.
this.products have prop items, look:
category: "3944_96469"
brand: "Apple"
format: "json"
nextPage: "/v1/paginated/items?category=3944_96469&brand=Apple&maxId=999066238&apiKey=8x83x2azqeaqvq7pzaqmvgg5"
totalPages: "1"
items: Array[2]
the map in items doesn't work:
{products.items.map(p => {
<p>p.name</p>;
})}
I don't know if this is because of the observable
Updated previous answer
I don't know if this is because of the observable
Most likely isn't, as I said, remove @observable and update the component manually:
componentDidMount() {
console.log(this.props.product);
this.props.product.fetchData()
.then(() => this.forceUpdate());
}
Forcing the update is something really strange, anyway the array does not work yet.
It's just temporarily to workaround that missing @observable, so that you can fix your problem without being concerned by Proxies, observables etc... (or use setState doesn't really matter)
This is resolved, should anyone need in the future:
https://codesandbox.io/s/o5vwozy8k9
Thank you for the help: @urugator :)
@viniarruda for issue etiquette: Could you describe what was the problem & solution was in the end, so that future readers of this thread are not left in the dark?
I'll close this issue as the originally issue seems answered, and otherwise too many conversion are going to be mixed up anyway
@viniarruda although it shows the correct results.console.log() still shows the proxy thing not the actual values. can you consider this again?
Mobx 5 uses proxies to implement the magic. The object should behave as normal array, not sure if we can do anything about the console output ... try
console.log(Mobx.toJS(this.favourite))to inspect the array ...
For future searchers, es6 syntax is:
import { toJS } from 'mobx';
console.log(toJS(this.favourite));
I've found the solution.
You need to put the response into a new variable, for example "myResponse":
class userState {
@observable favourite = [ ];
@action handleFavourite(credentials){
Fetcher.getFavourite(credentials).then(response => {
let myResponse = response;
this.favourite = myResponse.user.favourite;
console.log(this.favourite);
})
}
}
Mobx 5 uses proxies to implement the magic. The object should behave as normal array, not sure if we can do anything about the console output ... try
console.log(Mobx.toJS(this.favourite))to inspect the array ...For future searchers, es6 syntax is:
import { toJS } from 'mobx'; console.log(toJS(this.favourite));
it solves the problem, but it is strange - why it needs to be solved)
You can have a look at the "Target" if you're inspecting it in the dev console.
Most helpful comment
For future searchers, es6 syntax is: