3

I'm a junior developer that's fairly new to using Facebook for Developers. I'm hitting a wall with the ReactJs application I'm building and could use your help!

My boss has requested a Grid representation of the Page Plugin, not the actual Plugin itself. For this project, he's requested I make and use a test 'Page' I've found that DevExtreme's Data Grid seems to be the best option in terms of the desired visual, and I'm trying to call my Facebook Page using the Graph API documentation. I know it's hitting at least the area I want it to with my console.log because it's returning the error message.

Here are the errors my browser is returning:

Access to fetch at 'https://www.facebook.com/Feeds-Tester-170107151801959/' from origin 'https://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

GET https://www.facebook.com/Feeds-Tester-170107151801959/ net::ERR_FAILED

The link you'll see referenced in my URL variable has been triple checked to be the correct link. Since I'm using NodeJS, I tried installing the CORS npm package but I'm not 100% sure where to put it to use it, I'm wondering if that's the cause of the issue?

Here's my full code snippet (I'm using VS Code, if that helps):

/*global FB*/
import React from 'react';
import { DataGrid, Editing, Scrolling, Lookup, Summary, TotalItem } from 'devextreme-react/data-grid';
import { Button } from 'devextreme-react/button';
import { SelectBox } from 'devextreme-react/select-box';
import CustomStore from 'devextreme/data/custom_store';
import { formatDate } from 'devextreme/localization';
import 'whatwg-fetch';

const URL = 'https://www.facebook.com/Feeds-Tester-170107151801959/';
const REFRESH_MODES = ['full', 'reshape', 'repaint'];
class Grid extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fbData: null,
      ordersData: new CustomStore({
        key: 'OrderID',
        load: () => this.sendRequest(`${URL}`, 'GET'),
      }),
      requests: [],
      refreshMode: 'reshape'
    };
    this.clearRequests = this.clearRequests.bind(this);
    this.handleRefreshModeChange = this.handleRefreshModeChange.bind(this);

  var body = 'Reading JS SDK documentation';
  FB.api('/me/feed', 'post', { message: body }, function(response) {
    if (!response || response.error) {
      console.log('Error occured');
    } else {
      console.log('Post ID: ' + response.id);
    }
  })
}

  sendRequest(url, method, data) {
    method = method || 'GET';
    data = data || {};
    this.logRequest(method, url, data);
    if(method === 'GET') {
      return fetch(url, {
        method: method,
        credentials: 'include',
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
          'Access-Control-Allow-Origin': '*'
        }
      }).then(result => result.json().then(json => {
        if(result.ok) return json.data;
        throw json.Message;
      }));
    }

    const params = Object.keys(data).map((key) => {
      return `${encodeURIComponent(key) }=${ encodeURIComponent(data[key])}`;
    }).join('&');
    return fetch(url, {
      method: method,
      body: params,
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
      },
      credentials: 'include'
    }).then(result => {
      if(result.ok) {
        return result.text().then(text => text && JSON.parse(text));
      } else {
        return result.json().then(json => {
          throw json.Message;
        });
      }
    });
  }

  logRequest(method, url, data) {
    const args = Object.keys(data || {}).map(function(key) {
      return `${key }=${ data[key]}`;
    }).join(' ');

    const time = formatDate(new Date(), 'HH:mm:ss');
    const request = [time, method, url.slice(URL.length), args].join(' ');
    this.setState((state) => {
      return { requests: [request].concat(state.requests) };
    });
  }
  clearRequests() {
    this.setState({ requests: [] });
  }
  handleRefreshModeChange(e) {
    this.setState({ refreshMode: e.value });
  }
  render() {
    const { refreshMode, ordersData } = this.state;
    return (
      <React.Fragment>
        <DataGrid
          id="grid"
          showBorders={true}
          dataSource={ordersData}
          repaintChangesOnly={true}
        >
          <Editing
            refreshMode={refreshMode}
            mode="cell"
            allowAdding={true}
            allowDeleting={true}
            allowUpdating={true}
          />

          <Scrolling
            mode="virtual"
          />

          <Lookup dataSource={ordersData} valueExpr="Value" displayExpr="Text" />

          <Summary>
            {/* <TotalItem column="CustomerID" summaryType="count" />
            <TotalItem column="Freight" summaryType="sum" valueFormat="#0.00" /> */}
          </Summary>

        </DataGrid>
        <div className="options">
          <div className="caption">Options</div>
          <div className="option">
            <span>Refresh Mode: </span>
            <SelectBox
              value={refreshMode}
              items={REFRESH_MODES}
              onValueChanged={this.handleRefreshModeChange}
            />
          </div>
          <div id="requests">
            <div>
              <div className="caption">Network Requests</div>
              <Button id="clear" text="Clear" onClick={this.clearRequests} />
            </div>
            <ul>
              {this.state.requests.map((request, index) => <li key={index}>{request}</li>)}
            </ul>
          </div>
        </div>
      </React.Fragment>
    );
  }
}

export default Grid;

This is the link to the docs for the module I'm trying to reference

I'm trying to not bite off more than I can chew and just start with retrieving the data before I even think about manipulating it or sending any in return. Any insight or guidance you can provide would be greatly appreciated. Thank you!! :)

Katie Vee
  • 31
  • 4
  • You cannot fetch Facebook from the client browser, you would need to use a self hosted cors anywhere, or do it in your own API – iunfixit Aug 25 '21 at 16:40
  • https://stackoverflow.com/questions/43871637/no-access-control-allow-origin-header-is-present-on-the-requested-resource-whe – iunfixit Aug 25 '21 at 16:43
  • @iunfixit Thank you for that link! So you're saying to move the section with ```FB.api``` to my API and run that call in there instead of on the client side, just to confirm? – Katie Vee Aug 25 '21 at 16:49
  • No no, the fetch doesn't work with the Facebook URL, you can use the API(FB.api) instead, and it will work, replace fetch with a FB.api call, I will send an answer – iunfixit Aug 25 '21 at 16:50
  • If more code is needed on the answer I can edit it, basically sendRequest needs to work with FB.api instead of fetch, if you plan to use it for Facebook URLs – iunfixit Aug 25 '21 at 16:54

2 Answers2

2

Do not use fetch with the Facebook URL, it won't let it happen on the browser, instead, use the Facebook API for everything you need to do with it

For example, instead of fetching the page, use the api with the page

FB.api('/Feeds-Tester-170107151801959', function(response) {
  // ...
});

If you need to fetch the page, then you have to do it outside the browser environment or use a proxy like cors anywhere, but you can avoid that by using the Facebook API

iunfixit
  • 953
  • 3
  • 15
  • THANK you! :) I just ran the snippet you sent and added a ```console.log(response)```, I seemed to get a little farther this time but now I've got an error I also don't fully understand: ```{error: {…}} error: code: 100 error_subcode: 33 fbtrace_id: "A_RiTZEZ3dsCllkn9GSsOUx" message: "Unsupported get request. Object with ID 'Feeds-Tester-170107151801959' does not exist, cannot be loaded due to missing permissions, or does not support this operation. Please read the Graph API documentation at https://developers.facebook.com/docs/graph-api" type: "GraphMethodException"``` – Katie Vee Aug 25 '21 at 17:02
  • Does that imply it's something to do with this privacy/permissions on the Page? – Katie Vee Aug 25 '21 at 17:03
  • It probably has the wrong ID, I am not sure if it works with just the /Feeds-Tester-170107151801959, try /170107151801959 or check it on the page https://www.facebook.com/help/1503421039731588 – iunfixit Aug 25 '21 at 17:27
  • Ahh yup, thank you SO much! Tracking down the correct ID, it was able to return the console.log without issue :) Now I just need to figure out how to actually render the posts themselves ... thank you again! – Katie Vee Aug 25 '21 at 17:35
1

I was also getting these error. I found that the pageId, I was using was wrong‍♀️. These errors come only when your pageId is wrong or the domain is not whitelisted properly(I even tried with a ngrok url and it worked).

So the steps which I followed were:

  1. In buisness.facebook.com go to inbox from sidebar and select chat plugin. [https://i.stack.imgur.com/rDk5d.png]

  2. Click on setup to add your domain. [https://i.stack.imgur.com/exOi2.png]

  3. Pick a setup method(standard for react/nextjs) and setup chat plugin(add language, domain, copy code and paste it). [https://i.stack.imgur.com/hDArZ.png]

  4. You can add multiple domains. [https://i.stack.imgur.com/zGdgx.png]

  5. You will get pageId already embedded. [https://i.stack.imgur.com/iRT13.png]

Use this code and paste it in _document.js file in nextjs. and after deploying it will work perfectly. For any confusion please let me know. Thanks, Happy Coding ☺

ouflak
  • 2,458
  • 10
  • 44
  • 49