Facebook does not load image from og:image

 https://developers.facebook.com/tools/debug

https://stackoverflow.com/questions/20259142/facebook-open-graph-image-not-displaying

https://stackoverflow.com/questions/10346703/facebook-does-not-load-image-from-ogimage

When pulling a webpage from an URL, Facebook caches it's content for later. It means, that if Facebook once pulls data from your site, and than your site changes (for example your og:image tags change), Facebook will not change the image, because it already has everything cached on it's side.

Try visiting Facebook Debugger page and review what Facebook "sees". Using this tool forces Facebook to refresh data from the given URL. This is the best way to debug it.

When you make sure Facebook "sees" proper og:image tags, then make sure the images in the og:image are of proper minimum width/height (it's all explained in the fb debugger). Facebook will not use an image from og:image if it does not meet FB's criteria.

I strongly recommend this tool whenever there are any issues with content from your site on FB.


Why React setState/useState does not update immediately

 https://linguinecode.com/post/why-react-setstate-usestate-does-not-update-immediately#the-answer-why

The answer: They’re just queues

React this.setState, and useState does not make changes directly to the state object.

React this.setState, and React.useState create queues for React core to update the state object of a React component.

React setState callback function after state changes

If you’re using a class component, you will have to usethis.setState() to update the state of a React component.


this.setState(state, callback);

The second parameter this.setState() accepts is the callback function, and that’s where you’ll want to add your side effects.

This callback function will get triggered when React state has finished updating.


this.setState(newStateObject, () => {
  // ... do some other actions
});

The example above uses the arrow function, but you can do it with a traditional function syntax.


this.setState(newStateObject, function() {
  // ... do some other actions
});

But what if you’re not using this.setState, and you’re using React.useState?

How do you perform an action after React.useState hook has triggered?

Use React useEffect after state has changed

React.useState doesn’t have accept callback function that gets called after React state has actually been modified.

To perform side effects after state has change, you must use the React.useEffect hook.


React.useEffect(callback, deps);

React.useEffect accepts a callback function to perform your side effects or actions, and it accepts a list of dependencies in the form of an array.

That hook function will only activate if the values in the list change.

Let’s take a look at an example


let s;

const Foo = () => {
  const [counter, setCounter] = React.useState(0);

  // Emmulate componentDidMount lifecycle
  React.useEffect(() => {
    s = setInterval(() => {
      setCounter(state => (state +1));
    }, 1000);
  }, []);

  // This is for counter state variable
  React.useEffect(() => {
    if (counter > 9) {
      clearInterval(s);
    }
  }, [counter]);

  return <span>{counter}</span>;
};

The first React.useEffect hook has an empty array. Since there are no dependencies, it only gets triggered once.

But in the second React.useEffect hook, I added my state variable as a dependency.

Any time my state variablecounter, changes in value, then the second React.useEffect function will re-activate. So it behaves like the React componentDidUpdate lifecycle.

function FormattedDate(props) {

  return <h2>It is {props.date.toLocaleTimeString()}.</h2>;

}

class Clock extends React.Component {

  constructor(props) {

    super(props);

    this.state = {date: new Date()};

  }


  componentDidMount() {

    this.timerID = setInterval(

      () => this.tick(),

      1000

    );

  }


  componentWillUnmount() {

    clearInterval(this.timerID);

  }


  tick() {

    this.setState({

      date: new Date()

    });

  }


  render() {

    return (

      <div>

        <h1>Hello, world!</h1>

        <FormattedDate date={this.state.date} />

      </div>

    );

  }

}


function App() {

  return (

    <div>

      <Clock />

      <Clock />

      <Clock />

    </div>

  );

}


ReactDOM.render(<App />, document.getElementById('root'));


The useState set method is not reflecting a change immediately

 

Much like setState in Class components created by extending React.Component or React.PureComponent, the state update using the updater provided by useState hook is also asynchronous, and will not be reflected immediately.

Also, the main issue here is not just the asynchronous nature but the fact that state values are used by functions based on their current closures, and state updates will reflect in the next re-render by which the existing closures are not affected, but new ones are created. Now in the current state, the values within hooks are obtained by existing closures, and when a re-render happens, the closures are updated based on whether the function is recreated again or not.

Even if you add a setTimeout the function, though the timeout will run after some time by which the re-render would have happened, the setTimeout will still use the value from its previous closure and not the updated one.

setMovies(result);
console.log(movies) // movies here will not be updated

If you want to perform an action on state update, you need to use the useEffect hook, much like using componentDidUpdate in class components since the setter returned by useState doesn't have a callback pattern

useEffect(() => {
    // action on update of movies
}, [movies]);

As far as the syntax to update state is concerned, setMovies(result) will replace the previous movies value in the state with those available from the async request.

However, if you want to merge the response with the previously existing values, you must use the callback syntax of state updation along with the correct use of spread syntax like

setMovies(prevMovies => ([...prevMovies, ...result]));

While React's setState is asynchronous (both classes and hooks), and it's tempting to use that fact to explain the observed behavior, it is not the reason why it happens.

TLDR: The reason is a closure scope around an immutable const value.


Solutions:

  • read the value in render function (not inside nested functions):

      useEffect(() => { setMovies(result) }, [])
      console.log(movies)
    
  • add the variable into dependencies (and use the react-hooks/exhaustive-deps eslint rule):

      useEffect(() => { setMovies(result) }, [])
      useEffect(() => { console.log(movies) }, [movies])
    
  • use a temporary variable:

      useEffect(() => {
        const newMovies = result
        console.log(newMovies)
        setMovies(newMovies)
      }, [])
    
  • use a mutable reference (if we don't need a state and only want to remember the value - updating a ref doesn't trigger re-render):

      const moviesRef = useRef(initialValue)
      useEffect(() => {
        moviesRef.current = result
        console.log(moviesRef.current)
      }, [])
    

Explanation why it happens:

If async was the only reason, it would be possible to await setState().

However, both props and state are assumed to be unchanging during 1 render.

Treat this.state as if it were immutable.

With hooks, this assumption is enhanced by using constant values with the const keyword:

const [state, setState] = useState('initial')

The value might be different between 2 renders, but remains a constant inside the render itself and inside any closures (functions that live longer even after render is finished, e.g. useEffect, event handlers, inside any Promise or setTimeout).

Consider following fake, but synchronous, React-like implementation:

// sync implementation:

let internalState
let renderAgain

const setState = (updateFn) => {
  internalState = updateFn(internalState)
  renderAgain()
}

const useState = (defaultState) => {
  if (!internalState) {
    internalState = defaultState
  }
  return [internalState, setState]
}

const render = (component, node) => {
  const {html, handleClick} = component()
  node.innerHTML = html
  renderAgain = () => render(component, node)
  return handleClick
}

// test:

const MyComponent = () => {
  const [x, setX] = useState(1)
  console.log('in render:', x) // ✅
  
  const handleClick = () => {
    setX(current => current + 1)
    console.log('in handler/effect/Promise/setTimeout:', x) // ❌ NOT updated
  }
  
  return {
    html: `<button>${x}</button>`,
    handleClick
  }
}

const triggerClick = render(MyComponent, document.getElementById('root'))
triggerClick()
triggerClick()
triggerClick()
<div id="root"></div>

StaticImage

  import React , { useEffect , useRef } from "react" import { StaticImage } from "gatsby-plugin-image" impor...