Use在块编辑中选择始终返回默认存储值

时间:2021-09-11 作者:Lovor

考虑到我的自定义存储,当我尝试使用readItems选择器时,我总是获得默认的存储状态。选择器工作正常(在控制台中使用wp.data.select进行测试),但异步捕获值需要一些时间,我假定useSelect会记住第一个返回的值,这是默认的存储状态,不会响应存储更改。

如何修复此问题?

块编辑功能开始:

const LECTURERS_TABLE = \'tla_mit_lecturers\';


export default function Edit(props) {
    const { attributes, setAttributes } = props;

    const allItems = useSelect(select => select(\'REST-extra_table\').readItems(LECTURERS_TABLE)); 
存储:

import apiFetch from \'@wordpress/api-fetch\';
import { createReduxStore, register } from \'@wordpress/data\';

/**
 * returns table id from table name
 * @param  {} table
 */
function getTableId(table) {
    if (! table) {
        console.log(\'Table name not supplied for API\');
        return undefined;
    }
    const tableId = tableIds.indexOf(table);
    if (tableId == -1) {
        console.log(\'Wrong table name supplied to the API\');
        return undefined;
    }
    return tableId;
}

// items is array of tables - item[\'table_name\'][index] is individual item
const tableIds = [
    \'tla_mit_lecturers\',
]

const DEFAULT_STATE = {
    tables: [
        [\'default\']
    ],
};

const actions = {
    *createItem( item, table ) {
        const tableId = getTableId(table);
        const retValue = yield actions.fetchFromAPI(
            {
                path: \'/extra_table/v1/item?table=\' + table,
                method: \'POST\',
                data: item
            }
         );
        // retValue should be ID if insert is successful
        return retValue ?
            {
                type: \'CREATE_ITEM\',
                item: {ID: retValue, ...item},
                tableId
            } :
            {
                type: \'FETCH_ERROR\',
                error: \'unknown\'
            };
    },

    *deleteItem( ID, table ) {
        const tableId = getTableId(table);
        const retValue = yield actions.fetchFromAPI(
            {
                path: \'/extra_table/v1/item?table=\' + table + \'&ID=\' + ID,
                method: \'DELETE\'
            }
         );
        return retValue ?
            {
                type: \'DELETE_ITEM\',
                tableId,
                ID
            } :
            {
                type: \'FETCH_ERROR\',
                error: \'unknown\'
            };
    },

    *updateItem( ID, item, table ) {
        const tableId = getTableId(table);
        const retValue = yield actions.fetchFromAPI(
            {
                path: \'/extra_table/v1/item?table=\' + table + \'&ID=\' + ID,
                method: \'PUT\',
                data: item
            }
         );
        return retValue ?
            {
                type: \'UPDATE_ITEM\',
                item: {ID, ...item},
                ID,
                tableId
            } :
            {
                type: \'FETCH_ERROR\',
                error: \'unknown\'
            };
    },

    // action to set item values - hydrate in https://unfoldingneurons.com/2020/wordpress-data-store-properties-resolvers
    setItem( item, tableId ) {
        return {
            type: \'SET_ITEM\',
            item,
            tableId
        };
    },

    // action to set item values - hydrate in https://unfoldingneurons.com/2020/wordpress-data-store-properties-resolvers
    setAllItems( items, tableId ) {
        return {
            type: \'SET_ITEMS\',
            items,
            tableId
        };
    },

    fetchFromAPI( action ) {
        return {
            type: \'FETCH_FROM_API\',
            path: action.path,
                method: action.method,
                data: action.data,
                tableId: action.tableId
        };
    }
};

const store = createReduxStore( \'REST-extra_table\', {
    reducer( state = DEFAULT_STATE, action ) {
        switch ( action.type ) {
            case \'CREATE_ITEM\':
                return {
                    ...state,
                    tables: Object.assign([...state.tables], {[action.tableId]: [...state.tables[action.tableId], action.item] })
                };
            case \'UPDATE_ITEM\':
                return {
                    ...state,
                    tables: Object.assign(
                            [...state.tables],
                            {[action.tableId]:
                                Object.assign(
                                    state.tables[action.tableId],
                                    {[state.tables[action.tableId].findIndex(el => el.ID === action.ID)]: action.item}
                                )
                    })
                };
            case \'DELETE_ITEM\':
                return {
                    ...state,
                    tables: Object.assign([...state.tables], {[action.tableId]: state.tables[action.tableId].filter((el) => el.ID !== action.ID) })
                };
            // hydrate
            case \'SET_ITEM\':
                return {
                    ...state,
                    tables: Object.assign([...state.tables], {[action.tableId]: [...state.tables[action.tableId], action.item] })
                }
            case \'SET_ITEMS\':
                return {
                    ...state,
                    tables: Object.assign([...state.tables], {[action.tableId]: [...action.items] })
                }
            case \'FETCH_ERROR\':
                console.log(\'AJAX fetch error, code: \' + action.error);
                return state;

        }
                // console.error(\'Table name is not given!!! \'+action.type)

        return state;
    },

    actions,

    selectors: {
        readItem( state, ID, table ) {
            const tableId = getTableId(table);
            if (tableId === undefined)
                return undefined;
            if (state.tables[tableId])
                return state.tables[tableId].find(el => el.ID == ID);
            else
                return undefined;
        },
        readItems( state, table ) {
            const tableId = getTableId(table);
            if (tableId === undefined)
                return undefined;
            // return empty array if state.tables does not exist
            if (! state.tables[tableId])
                console.error(\'Requested table does not exist in state!\');
            return state.tables[tableId] || undefined;
        },
    },

    controls: {
        FETCH_FROM_API( action ) {
            return apiFetch(
                {
                    path: action.path,
                    // path: action.path,
                    method: action.method,
                    credentials: \'same-origin\',
                    mode:\'same-origin\',
                    // headers: {
                    //  \'Content-Type\': \'application/json\'
                    //  },
                    data: action.data
                } );
        },
    },

    resolvers: {
        *readItem( ID, table ) {
            const tableId = getTableId(table);
            const item = yield actions.fetchFromAPI(
                {
                    path: \'/extra_table/v1/item?table=\' + table + \'&ID=\' + ID,
                    method: \'GET\',
                    data: null,
                    tableId
                }
             );
            return item !== undefined ? actions.setItem( item, tableId ) : undefined;
        },
        *readItems( table ) {
            const tableId = getTableId(table);
            const allItems = yield actions.fetchFromAPI({
                    path: \'/extra_table/v1/all_items?table=\' + table,
                    method: \'GET\',
                    data: null,
                    tableId
            });
            return allItems !== undefined ? actions.setAllItems( allItems, tableId ) : undefined;
        },
    },
} );

register( store );

1 个回复
最合适的回答,由SO网友:Lovor 整理而成

结果是allItems 已填充。。。最后因此,必须扩展块开头的代码,以便在allItems 已填充:

export default function Edit(props) {
const { attributes, setAttributes } = props;

const allItems = useSelect(select => select(\'REST-extra_table\').readItems(LECTURERS_TABLE));
const [populated, setPopulated] = useState(false);

if (! populated && allItems.length !== 0) {
    // further code here
    setPopulated(true);
}
我所做的是每次渲染块时检查allItems 已填充,但将此信息保存在状态中,因此我希望在填充后运行的代码只运行一次。

相关推荐