infinum / eightshift-frontend-libs

Frontend library that exposes custom scripts and styles for modern WordPress projects
https://eightshift.com
MIT License
71 stars 12 forks source link

How to use useSelect #205

Closed marijang closed 3 years ago

marijang commented 3 years ago

Hey,

i want to get all post categories in options? So i put in options for example

const categories = useSelect(select =>
     select('core').getEntityRecords('taxonomy', 'category')
);

<SelectControl
          label={__('Post Type', 'b4b')}
          value={categoryId}
          options={categories.map(({id, name}) => ({label: name, value: id}))}
          onChange={onChangeCategory}
/>

and then in block.js

useSelect( ( select ) => {
    let query = {
      categories: [categoryId],
      order: 'asc',
    };
    return {posts: select('core').getEntityRecords('postType', 'post', query)}
  } );

Not working and i see that use select fire multiple times??? Also it is not good category_id...

marijang commented 3 years ago

My block

`import React, { useState } from 'react'; // eslint-disable-line no-unused-vars import { InspectorControls } from '@wordpress/block-editor'; import { Fragment } from '@wordpress/element'; import { Spinner } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { getActions } from '@eightshift/frontend-libs/scripts/editor'; import apiFetch from '@wordpress/api-fetch'; // eslint-disable-line import/no-extraneous-dependencies import manifest from './manifest.json'; import { FeaturedProjectsEditor } from './components/featured-projects-editor'; import { FeaturedProjectsOptions } from './components/featured-projects-options'; import { useSelect,withSelect } from '@wordpress/data';

export const B4bBlogCategory = (props) => {

//console.log(props); const { setAttributes, attributes, attributes: { postType, posts, category, postList },

} = props;

const [postCategories, setPostCategories] = useState(1); const [postResults, setPostResults] = useState(posts);

const query = { categories: [category], order: 'asc', };

const newPosts = useSelect( ( select ) => { return select('core').getEntityRecords('postType', 'post', query) }, [ category,query,posts ] );

useSelect((select) => { return { posts: select('core').getEntityRecords('postType', 'post', query) } },[posts,query]);

const actions = { ...getActions(props, manifest), onChangeCategory: (value) => { setAttributes({ category: value, }); }, };

return (

{!posts.length ? {__('Click to select posts', 'eightshift-boilerplate')} : } ); }; ` My options file `import React, { useState } from 'react'; // eslint-disable-line no-unused-vars import { __ } from '@wordpress/i18n'; import {useSelect,select} from '@wordpress/data'; import { PanelBody, SelectControl, FormTokenField, RangeControl } from '@wordpress/components'; export const BlogOptions = ({ attributes, actions }) => { const { postNames, postNumber, postType, postResults, category, postOffsetNumber } = attributes; const { onChangePostType, onChangePostNumber, onChangePostOffsetNumber, onChangeCategory, onChangePostInput, onChangePost, } = actions; let suggestions = []; useSelect((select) => { const categories = select('core').getEntityRecords('taxonomy', 'category'); }); return ( {onChangePostOffsetNumber && } {onChangePostNumber && } {categories && ({label: name, value: id}))} onChange={onChangeCategory} /> } {onChangePostInput && } ); }; `
MetarDev commented 3 years ago

Hi @marijang, the following code works for me:

  const categories = useSelect((select) => {
    return select('core').getEntityRecords('taxonomy', 'category');
  });

  const posts = useSelect((select) => {

    // Don't do anything if previous category hook didn't yet finish.
    if (!categories || categories.length === 0) {
      return [];
    }

    const query = {
      categories: [categories[0].id],
      order: 'asc',
    };
    return { posts: select('core').getEntityRecords('postType', 'post', query) };
  }) || [];

  console.log('posts', posts);

Not working and i see that use select fire multiple times???

Yes it fires on every re-render, same as with all other React code in the options / editor (React rerenders on every change to state / props). You need to guard against rerenders before hook has finished fetching the data (i.e. the renders where your categories & posts variables are still empty) which is what the following like does:

    // Don't do anything if previous category hook didn't yet finish.
    if (!categories || categories.length === 0) {
      return [];
    }

Also notice the }) || []; at the end of the useSelect which fetches posts. This is just a simple way to ensure you always get an array (and not null) in posts before select has done it's thing but it's not necessary if you guard against it.

Hope this helps.

marijang commented 3 years ago

Posts is readonly....:D

marijang commented 3 years ago

From manifest variable.

Scenario is

Options

  1. User choose blog category
  2. User pick number of posts
  3. User pick offset number

-Block.js onChangeCategory => refresh posts

marijang commented 3 years ago

if (!newPosts || newPosts.length !== 0) { setAttributes({ posts: newPosts, }); }

end up with

iruzevic commented 3 years ago

You can check this 3 blocks for more details on how to use useSelect

https://github.com/infinum/eightshift-frontend-libs/tree/release/4.0.0/blocks/init/src/Blocks/custom

marijang commented 3 years ago

is it save to run update?

iruzevic commented 3 years ago

Yes you can update the frontend-libs(package.json) and libs(composer.json). We didn't do any major breaking changes. But I can't guarantee

dingo-d commented 3 years ago

We didn't do any major breaking changes

Famous last words 😅 😂

marijang commented 3 years ago

Last time was show:D

marijang commented 3 years ago

Great work

marijang commented 3 years ago

what is lates version to update?

i put "@eightshift/frontend-libs": "^4.0.0", not working

dingo-d commented 3 years ago

It should be (if I'm not mistaken)

"@eightshift/frontend-libs": "git+https://github.com/infinum/eightshift-frontend-libs.git#release/4.0.0"
marijang commented 3 years ago

put inside update instructions: "add light color " inside manifest

marijang commented 3 years ago

and composer?

iruzevic commented 3 years ago

Please check the github.com eightshift-boilerplate there is everything set in composer and in package

marijang commented 3 years ago

We didn't do any major breaking changes

Hahhahah yep right.....:)