0

So I have an array is a class's state. Let's call it A. A is populated with objects of type B through a function f in the constructor. Later, I generate using f and new data, a new array of objects of type B called C. I then use setState({A: C}). However, this results in the data from the first array staying on the display. I'm not sure how to fix this at all.

Edit: code snippets

class ClassBox extends Component {
constructor(props) {
    super(props);
    // note data here uses the keys from the config file
    this.state = {
        data: this.props.data,
        filteredData: [],
        functionData: []
    };
    this.generateFunctionData = this.generateFunctionData.bind(this);
    this.state.functionData = this.generateFunctionData();
    this.state.filteredData = this.state.functionData;
    this.handleSearch = this.handleSearch.bind(this);
}

generateFunctionData(useData = false, data = null){
   return useData ? ProcessJSON.extractFunctions(data.functions).map((_function, index) =>
   {return createMethodBox(_function.Func_name, _function.Description, _function.Access_Mod, index)}) : ProcessJSON.extractFunctions(this.props.data.functions).map((_function, index) =>
   {return createMethodBox(_function.Func_name, _function.Description, _function.Access_Mod, index)});
}

handleSearch(input) {
    // convert to lower case to avoid capitalization issues
    const inputLowerCase = input.toString().toLowerCase();
    // filter the list of files based on the input
    const matchingList = this.state.functionData.filter((method) => {
            return method.props.name.toLowerCase().includes(inputLowerCase)
        }
    );
    this.setState({
        filteredData: matchingList
    });
}

render() {
    console.log(this.state.filteredData)
    return (
        <Container>
            <NameContainer>
                <h1>{this.state.data.className}</h1>
            </NameContainer>
            <ContentContainer>
                <DescriptionContainer>
                    {this.state.data.description}
                </DescriptionContainer>
                <StyledDivider/>
                <VarContainer>
                    <h1>Variables</h1>
                    <VarTableContainer>
                        <BootstrapTable
                            keyField="id"
                            data={[]}
                            columns={testColumns}
                            bordered={false}
                            noDataIndication="Table is Empty"
                            classes="var-table"
                        />
                    </VarTableContainer>
                    {/*{this.state.data.variables}*/}
                </VarContainer>
                <StyledDivider/>
                <MethodContainer>
                    <MethodHeader>
                        <h1>Methods</h1>
                        <StyledSearchBar onSearch={this.handleSearch}
                                         isDynamic={true} allowEmptySearch={false} minChars={0}
                                         className='searchBar'/>
                    </MethodHeader>
                    <Methods>
                        {this.state.filteredData}
                    </Methods>
                </MethodContainer>
            </ContentContainer>
        </Container>
    );
}


class Classes extends Component {
constructor(props) {
    super(props);
    this.state = {
        data: this.props.data,
        displayIndex: this.props.displayIndex
    };
    this.treeData = createTreeData(this.state.data);
    this.classBox = null
}

componentDidUpdate(prevProps, prevState, snapshot) {
    if(prevState.displayIndex !== this.props.displayIndex){
        const funcData = this.classBox.generateFunctionData(true, this.state.data[0][this.props.displayIndex]);
        console.log(funcData);
        this.classBox.setState({data: this.state.data[0][this.props.displayIndex], functionData: funcData, filteredData: funcData });
        this.classBox.forceUpdate();
        this.setState({displayIndex: this.props.displayIndex});
    }
}

render() {
    this.treeData = createTreeData(this.state.data);
    return (
        <Container>
            <FileTreeContainer>
                <StyledTreeMenu data={treeData}/>
            </FileTreeContainer>
            <ClassInfoContainer>
                <ClassBox ref = {el => this.classBox = el} data = {this.state.data[0][this.state.displayIndex]}/>
            </ClassInfoContainer>
        </Container>
    )
}

Classes contains an instance of ClassBox. After executing componentDidUpdate, the page still shows the old method boxes, even though functionData has changed.

EDIT 2: it's also worth noting that when I replace the class view with the landing view and go back to the class view it shows the page correctly.

2
  • Can you provide a code snippet of the react component? Commented Jul 10, 2019 at 2:31
  • I thought I had abstracted the problem pretty well. I'm confused why reassignment to an object in state and a call to render won't update the webpage as it should Commented Jul 10, 2019 at 2:36

1 Answer 1

1

The way your are setting the state should be correct, as you are setting it to a newly created array from .filter.

I think the issue is with you storing the method components in the filteredData state. Components should not be stored in state.

I believe your component is just re-rendering, but not removing the old generated components. Maybe try mapping the search input to the state and generate the method components that way.

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

4 Comments

How would I properly remove the old components?
Also when I had done the rendering in render, it'd still not update correctly.
I think you might have to rerender that entire child component. Try storing filteredData as a state of the parent component and pass a callback function to the child that allows you to modify the parent filteredData state from the child.
How would I go about rerendering the entire child component?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.