1

I have a body object with different types of elements: (strings, number, objects...).
I need to show the body in a table.
In order to do it, I need to print in one table the elements that aren't objects, and in another table the elements that are objects.

So I am calling the function to create an array with object elements (arrObj) and another array with the non object elements (arrSimple).

The problem is that when I go through the arrSimple array to print the elements in a table, this array is empty.

Could anyone guide me on how can I resolve this async problem?

const DetailResult = props => {

    ...
    const arrSimple = []
    const arrObj = []

    function organizeArray() {
        for (const prop in body) {
            if (typeof (body[prop]) != 'object') {
                arrSimple[prop] = (body[prop])
            } else if (typeof (body[prop]) == 'object') {
                arrObj[prop] = (body[prop])
            }
        }
    }

    function renderGeneralData() {
        organizeArray()

        arrSimple.map((key, i) => {
            <tr key={i}>
                <td width="25%">{key}</td>
                <td>{(arrSimple[key])}</td>
            </tr>
        })

    }

    return (

        <div>    
            <table className='table table-striped'>
                <tbody>
                    <tr>
                        <th>General Data</th>
                    </tr>
                    <tr>
                        {renderGeneralData()}
                    </tr>
                </tbody>
            </table>
        </div>
    )
}

export default DetailResult;

The body object comes from the app component.

class App extends Component {

    constructor() {
        super()
        this.state = {                       
            dataTable: {                
                transactionID: '',                             
                maxRows: 10,
                currentPage: 0,
                list: {
                    headerList: [],
                    body: []
                }
            }
        }
        this.search = this.search.bind(this)
     }

      search() {
        axios.get(URL)
            .then(resp => this.setState({
                dataTable: Object.assign(this.state.dataTable, {
                    list: [
                        {headerList: ['App name', 'Date', 'Bio data', 'Is verified', 'Actions']},
                        {body: resp.data},
                    ],
                }),

            }))
            .catch(function (error) {
                console.log(error);
            })
    }

I have a component that contains a search field to make a request

 const SearchComponent = props => {    

        const renderDetailResult = 
            <DetailResult list={props.dtObject.list}
                search={props.search}
            /> 

         return (
            <div role='form' className='searchID'>
                <ContentHeader title={props.componentHeaderTitle} />
                <Grid cols='12 9 10'>
                    <input id="cpf" className='w-25 form-control'
                        placeholder='Type the ID'
                    />
                </Grid>
                <Grid cols='12 3 2'>
                    <IconButton style='primary' icon='search'
                        onClick={props.search}>
                    </IconButton>
                </Grid>
                <Grid cols='12'>
                    {renderDetailResult}
                </Grid>

            </div>
        )
    }

    export default SearchComponent
5
  • 1
    Where is comming the body ? Please show the code where you get it Commented May 27, 2019 at 13:06
  • @Vencovsky I updated the question Commented May 27, 2019 at 13:11
  • And where do you call search ? The body object comes from the app component. where are you passing it? Looking at the two component codes you add, I can't see any relation between then. Commented May 27, 2019 at 13:29
  • Render <DetailResult /> conditionally, when body array is not empty. Commented May 27, 2019 at 13:35
  • @Vencovsky I added the code that link the components. Sorry, I thought it was irrelevent to my question. Commented May 27, 2019 at 13:50

1 Answer 1

1

The reason why nothing appears is that you are calling a function that returns nothing, so there isn't anything to render.

You need to return the .map and return the elements you want.

function renderGeneralData() {
    organizeArray()

    // added return
    return arrSimple.map((key, i) => (
        <tr key={i}>
            <td width="25%">{key}</td>
            <td>{(arrSimple[key])}</td>
        </tr>
    ))

}

Observation

You are rendering <tr> inside <tr>. I recommend removing the

return arrSimple.map((key, i) => (
    //returning tr
    <tr key={i}>
        <td width="25%">{key}</td>
        <td>{(arrSimple[key])}</td>
    </tr>
))

<tr>
    // returned tr inside another tr
    {renderGeneralData()}
</tr>

I'm not sure how you want to display your data, but I recommend removing one of the tr tag.

Quick tip

If you want to remove the tr that is inside .map you should use React.Fragment

return arrSimple.map((key, i) => (
    <React.Fragment key={i}>
        <td width="25%">{key}</td>
        <td>{(arrSimple[key])}</td>
    </React.Fragment>
))

Edit:

I also noticed something weird in your code in this part

arrSimple.map((key, i) => (
    <tr key={i}>
        <td width="25%">{key}</td>
        <td>{(arrSimple[key])}</td>
    </tr>
))

In this part of the code, key will be an element of arrSimple. If you do arrSimple[key] it will probably return undefined. Here is an example

arr = ['hey', 'this', 'is', 'bad', '!']
console.log(arr.map((key, i) => arr[key]))

Sign up to request clarification or add additional context in comments.

2 Comments

tku so much for the answer and for the explanation.
@mr.abdo take a look at the edit, maybe it will help you in other things too

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.