Reactjs React属性是空对象,而不是预期的数组
我正试图从Office UI Fabirc控制库中实现一个Reactjs React属性是空对象,而不是预期的数组,reactjs,typescript,office-ui-fabric,Reactjs,Typescript,Office Ui Fabric,我正试图从Office UI Fabirc控制库中实现一个GroupedList,我离演示代码不远。出于某种原因,当将items数组传递到我通过props(TimeDisplay)构建的函数组件中时,我丢失了列表。我为itemsArray参数获取了一个空Javascript对象,而不是在调用“Home”组件中设置的伪数组。为什么我不去拿我的小阵列?我猜这只是我错过了一些关于React工作方式的东西,但我希望能有任何见解 相关代码 Home.tsx import React, { Componen
GroupedList
,我离演示代码不远。出于某种原因,当将items数组传递到我通过props(TimeDisplay)构建的函数组件中时,我丢失了列表。我为itemsArray
参数获取了一个空Javascript对象,而不是在调用“Home”组件中设置的伪数组。为什么我不去拿我的小阵列?我猜这只是我错过了一些关于React工作方式的东西,但我希望能有任何见解
相关代码
Home.tsx
import React, { Component } from 'react';
import { TimeSubmitter } from './TimeSubmitter'
import { TimeDisplay, TimeEntry } from './TimeDisplay'
type HomeProps = {
}
export class Home extends Component<HomeProps> {
static displayName = Home.name;
private items: TimeEntry[] = new Array<TimeEntry>();
constructor(props: HomeProps){
super(props);
this.items.push(
{
client: "Apple",
hours: 1,
timeCode: "MD",
loggedDate: new Date()
});
}
render () {
return (
<div>
<TimeDisplay title="Time Logged this Period" items={this.items} />
</div>
);
}
}
import React,{Component}来自'React';
从“/TimeSubmitter”导入{TimeSubmitter}
从“/TimeDisplay”导入{TimeDisplay,TimeEntry}
类型HomeProps={
}
导出类Home扩展组件{
静态显示名称=Home.name;
私有项:TimeEntry[]=new Array();
构造器(道具:家庭道具){
超级(道具);
这个。项目。推(
{
客户:“苹果”,
时间:1,,
时间码:“MD”,
loggedDate:新日期()
});
}
渲染(){
返回(
);
}
}
TimeDisplay.tsx
import React, { FunctionComponent, useState } from 'react';
import { GroupedList, IGroup } from 'office-ui-fabric-react/lib/GroupedList';
import { IColumn, DetailsRow } from 'office-ui-fabric-react/lib/DetailsList';
import { FocusZone } from 'office-ui-fabric-react/lib/FocusZone';
import { Selection, SelectionMode, SelectionZone } from 'office-ui-fabric-react/lib/Selection';
type TimeDisplayProps = {
title: string,
items: TimeEntry[]
}
export type TimeEntry = {
client: string,
hours: number,
timeCode: string,
loggedDate: Date
}
const buildGroups = (items: Array<TimeEntry>) => {
let groups = new Array<IGroup>();
let hashSet = new Set<string>();
for (let index = 0; index < items.length; index++) {
const element = items[index];
if(!hashSet.has(element.client)){
groups.push({
key: element.client,
name: element.client,
startIndex: 0,
count: 10
});
hashSet.add(element.client);
}
}
return groups;
}
const buildColumns = (item: TimeEntry[]) => {
return (Object.keys(item)
.map(
(key: string): IColumn => ({
key: key,
name: key,
fieldName: key,
minWidth: 300
})
));
}
export const TimeDisplay: FunctionComponent<TimeDisplayProps> = (title, itemsArray) =>{
const [items, setItems] = useState(itemsArray);
const [selection, setSelection] = useState(new Selection());
const [groups, setGroups] = useState(buildGroups(itemsArray));
const [columns, setColumns] = useState(buildColumns(itemsArray[0]));
const onRenderCell = (nestingDepth?: number | undefined, item?: any, index?: number | undefined) => {
if(nestingDepth != undefined && index != undefined){
return (
<DetailsRow
columns={columns}
groupNestingDepth={nestingDepth}
item={item}
itemIndex={index | 0}
selection={selection}
selectionMode={SelectionMode.multiple}
compact={false}
/>);
}
}
return (
<FocusZone>
<SelectionZone selection={selection} selectionMode={SelectionMode.single}>
<GroupedList
items={items}
onRenderCell={onRenderCell}
selection={selection}
selectionMode={SelectionMode.single}
groups={groups}
/>
</SelectionZone>
</FocusZone>);
}
import React,{FunctionComponent,useState}来自'React';
从“office ui fabric react/lib/GroupedList”导入{GroupedList,IGroup};
从“office ui fabric react/lib/DetailsList”导入{IColumn,DetailsRow};
从“office ui fabric react/lib/FocusZone”导入{FocusZone};
从“office ui fabric react/lib/Selection”导入{Selection,SelectionMode,SelectionZone};
类型TimeDisplayProps={
标题:字符串,
项目:时间输入[]
}
导出类型时间项={
客户机:字符串,
小时数:,
时间码:字符串,
日志日期:日期
}
const buildGroups=(项:数组)=>{
设groups=newarray();
设hashSet=newset();
for(让index=0;index{
返回(对象键(项)
.地图(
(键:字符串):IColumn=>({
钥匙:钥匙,
姓名:key,,
字段名:key,
最小宽度:300
})
));
}
导出常量时间显示:FunctionComponent=(标题,itemsArray)=>{
const[items,setItems]=useState(itemsArray);
const[selection,setSelection]=useState(newselection());
const[groups,setGroups]=useState(buildGroups(itemsArray));
const[columns,setColumns]=useState(buildColumns(itemsArray[0]);
const onRenderCell=(嵌套深度?:编号未定义,项目?:任何,索引?:编号未定义)=>{
if(嵌套深度!=未定义和索引!=未定义){
返回(
);
}
}
报税表(
);
}
此项目仅是主组件上的一个属性。更改它不会导致重新渲染Home或传递给它的TimeDisplay组件。您还需要对TimeDisplay中收到的道具进行分解
所以首先,你应该使用状态;在构造函数中,您可以编写如下内容:
import React, { Component } from 'react';
import { TimeSubmitter } from './TimeSubmitter';
import { TimeDisplay, TimeEntry } from './TimeDisplay';
type HomeProps = {};
export class Home extends Component<HomeProps> {
static displayName = Home.name;
private items: TimeEntry[] = new Array<TimeEntry>();
constructor(props: HomeProps) {
super(props);
// set initial state with your object inside the items array
this.state = {
items: [
{
client: 'Apple',
hours: 1,
timeCode: 'MD',
loggedDate: new Date()
}
]
};
}
render() {
// change this.items to this.state.items
return (
<div>
<TimeDisplay title='Time Logged this Period' items={this.state.items} />
</div>
);
}
}
将在数组上使用forEach方法,如
items.forEach(element => {
if (!hashSet.has(element.client)) {
groups.push({
key: element.client,
name: element.client,
startIndex: 0,
count: 10
});
hashSet.add(element.client);
}
return groups;
});
希望这一切都有意义 此.items
只是主组件上的一个属性。更改它不会导致重新渲染Home或传递给它的TimeDisplay组件。您还需要对TimeDisplay中收到的道具进行分解
所以首先,你应该使用状态;在构造函数中,您可以编写如下内容:
import React, { Component } from 'react';
import { TimeSubmitter } from './TimeSubmitter';
import { TimeDisplay, TimeEntry } from './TimeDisplay';
type HomeProps = {};
export class Home extends Component<HomeProps> {
static displayName = Home.name;
private items: TimeEntry[] = new Array<TimeEntry>();
constructor(props: HomeProps) {
super(props);
// set initial state with your object inside the items array
this.state = {
items: [
{
client: 'Apple',
hours: 1,
timeCode: 'MD',
loggedDate: new Date()
}
]
};
}
render() {
// change this.items to this.state.items
return (
<div>
<TimeDisplay title='Time Logged this Period' items={this.state.items} />
</div>
);
}
}
将在数组上使用forEach方法,如
items.forEach(element => {
if (!hashSet.has(element.client)) {
groups.push({
key: element.client,
name: element.client,
startIndex: 0,
count: 10
});
hashSet.add(element.client);
}
return groups;
});
希望这一切都有意义 您在功能组件的定义中缺少了解构。因此,功能组件获得一个props
参数作为第一个参数,它包含所有作为对象键的props。如果要在定义中直接分解它们,则需要大括号。现在,功能组件中的itemsArray
正在引用功能组件获取的第二个参数,这是使用React.forwardRef(…)
转发的引用
因此,在道具关键点周围用花括号定义功能组件,如下所示:
export const TimeDisplay: FunctionComponent<TimeDisplayProps> = ({title, itemsArray}) =>{
...
export const TimeDisplay:FunctionComponent=({title,itemsArray})=>{
...
您在功能组件的定义中缺少了解构。因此,功能组件获得了一个props
参数作为第一个参数,该参数包含所有作为对象键的props。如果您想在定义中直接解构它们,则需要大括号。现在,请在y中使用itemsArray
我们的功能组件引用了功能组件获取的第二个参数,这是使用React.forwardRef(…)
转发的引用
因此,在道具关键点周围用花括号定义功能组件,如下所示:
export const TimeDisplay: FunctionComponent<TimeDisplayProps> = ({title, itemsArray}) =>{
...
export const TimeDisplay:FunctionComponent=({title,itemsArray})=>{
...
这是有道理的,我并不惊讶这是一件愚蠢的事情。我也同意forEach。我最初是这样做的,但我不断收到抱怨说“items.forEach不是一个函数”所以我把它改成了for循环。不确定它为什么要这样做。我猜在原始代码中,items
没有初始化为数组(原因在答案中概述),所以当它寻找forEach方法时,它将无法找到它。哈,这是有意义的。我一定会把forEach放回那里!我今晚会测试并接受它