首页 \ 问答 \ 从axios调用中React redux设置初始状态(React redux setting initial state from axios call)

从axios调用中React redux设置初始状态(React redux setting initial state from axios call)

我有一个使用Redux和axios的React应用程序。 在我从服务器获取一些信息之前,我不想要任何渲染,我通过axios检索。

我认为最好的方法是通过基于axios调用初始化redux状态。

但是,我的函数似乎没有及时返回任何状态初始化...

function getUserData() {
    if (Auth.loggedIn()) { //leaving this here bc it could be important; Auth is another class and loggedIn returns a boolean
        axios.get('/route').then(res => {
            console.log(res.data); //This prints the right thing (an object)
            return res.data;
        });
    } else {
        return ' '; //This works fine; state gets initialized to ' '
    }
}

    let userData = getUserData();
    console.log(userData); //When getUserData() returns ' ', this prints ' '. However, when getUserData() returns my object, this prints undefined.

    const initialState = {
        userData: userData
    };

我意识到这可能是一个问题,getUserData()是异步的,并且在getUserData()之前运行的console.log(userData)已经完成。 但是,我尝试过:

getUserData().then(function(userData) {
     console.log(userData);
});

并收到'TypeError:无法读取属性'然后'未定义'。 我的函数显然没有返回一个promise,所以这是不是意味着它不是异步的?

有任何想法吗?

或者,有更好的方法吗? 我总是可以设置初始状态,然后立即更改它,并使渲染等待条件渲染完成更改,但这看起来肯定更糟。


I have a React app which uses Redux and axios. I do not want anything to render before I have some information from the server, which I am retrieving via axios.

I thought that the best way to do this would be by initializing redux state based on that axios call.

However, my function does not seem to be returning anything in time for state initialization...

function getUserData() {
    if (Auth.loggedIn()) { //leaving this here bc it could be important; Auth is another class and loggedIn returns a boolean
        axios.get('/route').then(res => {
            console.log(res.data); //This prints the right thing (an object)
            return res.data;
        });
    } else {
        return ' '; //This works fine; state gets initialized to ' '
    }
}

    let userData = getUserData();
    console.log(userData); //When getUserData() returns ' ', this prints ' '. However, when getUserData() returns my object, this prints undefined.

    const initialState = {
        userData: userData
    };

I realize that this could be a problem with getUserData() being asynchronous, and console.log(userData) running before getUserData() has finished. However, I tried:

getUserData().then(function(userData) {
     console.log(userData);
});

And received 'TypeError: Cannot read property 'then' of undefined'. My function is obviously not returning a promise, so doesn't that mean it's not asynchronous?

Any ideas?

Alternatively, is there a better way of doing this? I could always set initial state and then immediately change it, and make rendering wait for the change to be complete with a conditional render, but that definitely seems worse.


原文:https://stackoverflow.com/questions/50892683
更新时间:2023-08-28 11:08

最满意答案

onPress道具采用了一个回调函数,当该元素被“按下”时调用该函数。

该函数应该是一个事件处理程序。 通常使用event对象调用事件处理程序。 我认为你误解了如何调用回调函数。 请仔细阅读。

因此,您的函数在第一个参数中使用事件对象(React中的代理事件对象)调用,而undefined为第二个参数。

改为:

<TouchableOpacity onPress={() => this.launchGame(provider, gameId)}>

但还有更多。 由于闭包的工作方式,这可能无法正常工作。 看到这里

基本上,您在每个循环中更改providergameId的值。 回调函数在其闭包中有这些变量,但它们不存储定义这些函数时的确切值(基本上,当按下所有的gameId时,您将获得存储在providegameId的最后一个值)。 这也是因为你使用var而不是letconst ,它们具有函数作用域而不是块作用域。

你可以这样做:

<TouchableOpacity onPress={() => {
  var provider = gamesList[i].provider;
  var gameId = gamesList[i].gameId.toString();
  this.launchGame(provider, gameId)
}}>
  <ResponsiveImage
    source={{uri: gamesList[i].imageUrl}}
    initWidth="200"
    initHeight="120"
    defaultSource={require('./splash-tile2.png')}
  />
</TouchableOpacity>

这样,您可以直接在每个回调的范围中定义这些变量。 (或者,如果你可以使用letconst ,在定义providergameId时将var更改为const ,你的代码应该可以工作。)


The onPress prop for TouchableOpacity takes a callback function that is called when that element is "pressed".

This function is supposed to be an event handler. It is conventional that an event handler is called with an event object. I think you are misunderstanding how callback functions are called. Please go through this.

So, your function is called with the event object (proxy event object in React) in the first argument and undefined as the second argument.

Do this instead:

<TouchableOpacity onPress={() => this.launchGame(provider, gameId)}>

But there is more. This probably won't work properly because of how closures work. See here.

Basically, you are changing the value in provider and gameId on each loop. The callback functions have these variables in its closure, but they do not store the exact value that was there when these functions were defined (basically, you'll get the last value stored in provide and gameId when pressing on all of the TouchableOpacity). This is also because you are using var, instead of let or const, which had function scope and not block scope.

You can do this instead:

<TouchableOpacity onPress={() => {
  var provider = gamesList[i].provider;
  var gameId = gamesList[i].gameId.toString();
  this.launchGame(provider, gameId)
}}>
  <ResponsiveImage
    source={{uri: gamesList[i].imageUrl}}
    initWidth="200"
    initHeight="120"
    defaultSource={require('./splash-tile2.png')}
  />
</TouchableOpacity>

This way you are defining these variables in each callback's scope directly. (Or, if you can use let or const, change var to const when defining provider and gameId and your code should work.)

相关问答

更多
  • 也有反应原生Facebook广告看看: 反应原生Facebook的广告 这个插件允许你实现原生广告,唯一的缺点是安装过程有点少,但它确实有效。 它还需要安装react-native-fbsdk ,以便您的广告在用户登录后即可向您的用户制作相关的广告。 目前react-native-admob目前还不支持原生广告,但您可以通过以下方式实现它: Add some content here
  • onPress道具采用了一个回调函数,当该元素被“按下”时调用该函数。 该函数应该是一个事件处理程序。 通常使用event对象调用事件处理程序。 我认为你误解了如何调用回调函数。 请仔细阅读。 因此,您的函数在第一个参数中使用事件对象(React中的代理事件对象)调用,而undefined为第二个参数。 改为: this.launchGame(provider, gameId)}> 但还有更多。 由于闭包的工作方式,这可能无法正常工作。 看 ...
  • 我终于在第二天发现你可以用整个表达式来替代缺少变量的弧形。 this.points = [ d3.shape.arc().outerRadius(this.props.outerRadius).innerRadius(this.props.innerRadius).centroid(this.props.arcData), d3.shape.arc().outerRadius(this.props.radius*0.95).innerRadius(this.props.radius*0.95 ...
  • Picker的回调给你itemValue和itemIndex ,你必须在你的啤酒数组中进行推送并在构造函数中进行bind constructor(props){ super(props); this.state = { beer: [] }; this.addBeer = this.addBeer.bind(this); } addBeer(itemValue, itemIndex){ this.setState((state) => { ...
  • 在被问到这个问题的9个月里,有很多变化。 您不应该使用上下文https://facebook.github.io/react/docs/context.html 传递Redux周围的动作是最流行的flex样式扩展,我建议使用它。 http://redux.js.org/ 我建议有纯组件,只要有内部状态,如果需要,没有功能作为组件之间的道具传递。 a lot have changed during these 9 months when question was asked. You should not u ...
  • 它没有意义,因为this.state.list和this.props.list不应该是不同的。 至少这是我从你提供的代码中可以读到的内容。 我能说的是: 元素类型无效:期望一个字符串(对于内置组件)或>一个类/函数(对于复合组件)但得到:undefined。 您可能忘记从其定义的文件中导出组件。 它说'undefined'被用作一种类型,它不是! 我的猜测是未定义。 React-native没有内置的ListItem类型。 react-native-elements确实如此,但 ...
  • 由于您使用v1.0.0.beta4 ,因此它不支持onClearText ,您需要用onClear替换它。 也因为你已经参考了this参数 this.search = search} onClear={()=>this.handleOnClearText()} <== Here /> 因此不要使用胖箭头功能 handleOnClearText () { if(this.search != null) this.search ...
  • 你可以尝试做这样的事情,在函数handlePickerSelection中,你可以将数值放入数组元素的索引i let pickers = []; for ( let i = 0; i < numberOfPickers; i++) { pickers[i] = handlePickerSelection(value, i) }>
  • 您可以使用来自react-native zoomIdentity和来自d3-zoom zoomIdentity来达到此目的。 代码示例看起来像这样 componentWillMount() { this._panResponder = PanResponder.create({ onMoveShouldSetPanResponder: (evt, gestureState) => true, onPanResponderMove: (event, { dx, dy } ...
  • 您可以使用setState.I将为您显示有关subject的示例。您应该查看以下代码。 import React,{Component} from "react" import {View,TouchableOpacity,Text} from "react-native" class Test extends Component{ state ={ count = 0 } changeCount(){ this. ...

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。