最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React - How to pass returned data from an exported function to a component? - Stack Overflow

programmeradmin7浏览0评论

How can I pass data I receive from a get request pass over to a component? Whatever I tried wouldn't work but my thinking was as the code below shows.. Thanks!

    export function data() {
        axios.get('www.example.de')
            .then(function(res) {
                return res.data
            })
            .then(function(data) {
                this.setState({
                    list: data
                })
            })
    }

    import {data} from './api.js';

    class Test extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                list: ""
            };
        }

        componentWillMount() {
            data();
        }
        render() {
            return <p > this.state.list < /p>
        }
    }

How can I pass data I receive from a get request pass over to a component? Whatever I tried wouldn't work but my thinking was as the code below shows.. Thanks!

    export function data() {
        axios.get('www.example.de')
            .then(function(res) {
                return res.data
            })
            .then(function(data) {
                this.setState({
                    list: data
                })
            })
    }

    import {data} from './api.js';

    class Test extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                list: ""
            };
        }

        componentWillMount() {
            data();
        }
        render() {
            return <p > this.state.list < /p>
        }
    }
Share Improve this question asked Jul 29, 2017 at 14:27 javascriptingjavascripting 1,1535 gold badges26 silver badges47 bronze badges 1
  • what do you get when you do console.log("data.." + data()) inside componentWillMount. – abdul Commented Jul 29, 2017 at 14:36
Add a comment  | 

4 Answers 4

Reset to default 9

You call this.setState inside of data()->then callback, so this is context of the then callback function. Instead you should use arrow functions (it does not have its own context) and pass component's this to data function using call

export function data() {
    axios.get('www.example.de')
        .then(res => res.data)
        .then(data => {
            this.setState({
                list: data
            })
        })
}

import {data} from './api.js';

class Test extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            list: ""
        };
    }

    componentWillMount() {
        data.call(this);
    }
    render() {
        return <p > this.state.list < /p>
    }
}

However, your data services must not know about setState and, event more, expect passing this from react component. Your data service must be responsible for retrieving data from server, but not for changing component state, see Single responsibility principle. Also, your data service can be called from another data service. So your data service should return promise instead, that can be used by component for calling setState.

   export function data() {
       return axios.get('www.example.de')
           .then(res => res.data)
   }

and then

componentWillMount() {
    data().then(data=>{
        this.setState({
            list: data
        })
    });
}

your api shouldn't know anything about your component, you can easily do this with callback, like so -

export function data(callback) {
    axios.get('www.example.de')
        .then(res => callback({ data: res.data }))
        .catch(err => callback({ error: err }));
}

By doing this you can easily unit test your api

So in your Test component, you simply do -

componentWillMount() {
  data(result => {
    const { data, error } = result;
    if (error) {
      // Handle error
      return;
    }

    if (data) {
      this.setState({ list: data });
    }
  });
}

Your request is a promise so you can simply return that from the imported function and use the eventual returned result of that within the component. You only want to be changing the state of the component from within the component.

export function getData(endpoint) {
  return axios.get(endpoint);
}

Note I've changed the name of the function to something more "actiony".

import { getData } from './api.js';

class Test extends React.Component {
  constructor(props) {
    super(props);

    // Your state is going to be an array of things, so
    // initialise it with an array to spare confusion
    this.state = { list: [] };
  }

  // I use ComponentDidMount for fetch requests
  // https://daveceddia.com/where-fetch-data-componentwillmount-vs-componentdidmount/
  componentDidMount() {

    // We've returned a promise from `getData` so we can still use the
    // promise API to extract the JSON, and store the parsed object as the
    // component state
    getData('www.example.de')
      .then(res => res.data)
      .then(list => this.setState({ list }))
  }
}

Your external function doesn't have the correct context of this, so you'll need to call it with the correct context from within the component:

componentWillMount() {
    data.call(this);
}

However, inside the API call, it still won't have the correct this context, so you can set a variable to point to this inside the data() function:

export function data() {
  let that = this;
  axios('http://www.url.com')
    .then(function(res) {
      return res.data
    })
    .then(function(data) {
      that.setState({
        list: data
      })
    })
}

Details of the this keyword

However, it's generally considered better practice to only handle your state manipulation from with the component itself, but this will involve handling the asynchronous nature of the GET request, perhaps by passing in a callback to the data() function.

EDIT: Updated with asynchronous code

//api.js
data(callback){
  axios.get('www.url.com')
    .then(res => callback(res));
}

//component.jsx
componentWillMount(){
  data(res => this.setState({list: res}));
}
发布评论

评论列表(0)

  1. 暂无评论