Bundle.js not recognizing one of my files? - javascript

Please bear with me because I am a javascript newbie, and just starting to learn react.
I am trying to make a small app but I keep getting an error that one of my files is not found... specifically this:
bundle.js:56 Uncaught Error: Cannot find module "./components/search_bar"
My file structure is that I have my index.js in a folder called src, then my search bar(search_bar.js) in a folder called components. I have triple checked the spelling on them but I continue to get this error.
This is my index.js
import SearchBar from './components/search_bar';
import React from 'react';
import ReactDOM from 'react-dom';
//Create a componant (some /HTML)
const API_KEY = 'AIzaSyC3Z3qTpvAacDLYEIxaueKflFJbWvdIHsw';
const App = () => {
return (
<div>
<SearchBar />
</div>
);
}
// Put that componant on the page (the DOM)
ReactDOM.render(<App />, document.querySelector('.container'));
And this is my search_bar.js
import React, { Component } from 'react';
class SearchBar extends Component {
contructor(props) {
super(props);
// when user updates the search bar this term will get updated.
this.state = { term: ''};
}
render() {
//update state
//use set state everywhere besides constructor!!
return (
<div>
<input onChange={event => this.setState({term: event.target.value})}
/>
Value of the input: {this.state.term}
</div>
);
}
}
export default SearchBar;
Any Ideas as to what I am doing wrong here?

Can you confirm the following directory structure?
my_project/src/index.js
my_project/src/components/search_bar.js
It seems like your current directory structure might instead look like this:
my_project/src/index.js, my_project/components/search_bar.js

AHHH I left an 's' out of constructor... so search_bar.js was unable to compile. I have been looking at this for about an hour now...

Related

React: store uploaded array into global variable?

I'm currently working on using React to upload a CSV file and convert the data to an array so I can access phone numbers. I've actually got it almost completely functional, with just one problem: I can't figure out how to store the array properly in a variable (dataDump) on the global level. It stores it inside another array.
Here's a picture of my console so you can see what I mean.
I'm able to access the contents of dataDump if I use dataDump[0] (as seen in the function for handleClick), but that won't work for a global variable. I need to be able to send the array's values to other components/files, so I don't think having to call it like that will work. Chances are I'm over-complicating this in my head and the answer is incredibly simple, but I've spent the past 2-3 weeks learning React, Twilio, Mongodb etc. from scratch so my brain's not cooperating.
I'll appreciate any help! Thanks! Code below. (Note this is a component that's imported to the App page.)
import React from "react";
import CSVReader from "react-csv-reader";
var dataDump = [];
console.log(dataDump);
const papaparseOptions = {
header: true,
dynamicTyping: true,
skipEmptyLines: true,
transformHeader: header => header.toLowerCase().replace(/\W/g, "_"),
complete: function(results) {
dataDump.push(results.data);
console.log(dataDump);
var rows = results.data;
let numbers = rows.map(a => a.phone_number); //make the results ONLY the phone numbers
// console.log(numbers);
document.getElementById("data2").innerHTML=numbers; //display the phone numbers
}
};
class Import extends React.Component {
constructor(props) {
super(props);
this.state = {data:[]};
this.handleClick = this.handleClick.bind(this);
}
handleForce = data => {
// console.log(data.length);
console.log(data);
this.setState({data: data});
};
handleClick = () => {
console.log("success");
console.log(this.state.data);
console.log("Next is Numbies:");
let numbies = dataDump[0].map(a => a.phone_number);
console.log(numbies);
document.getElementById("data").innerHTML=numbies;
}
render() {
return (
<div className="container">
<CSVReader
className="csv-input"
label="Select CSV file to import"
onFileLoaded={this.handleForce}
parserOptions={papaparseOptions}
/>
<div>
</div>
<button onClick={this.handleClick.bind(this)}>
Test
</button>
<div id="data" />
<div id="data2" />
<div id="data3">
</div>
</div>
);
}
}
export default Import;
// export default DataController;
Under the hood React-Redux is using context and hooks these days, so don't bother implementing a Redux stack until you've outgrown the simpler, React API, or at least you've fixed your issue. Folks joke that Redux is like shooting a fly with a bazooka. More info on React-Redux internals here and here's the documentation for React's Context.
Some psuedo-code to get you on the right path:
// context.js
import { createContext } from 'react';
export const Store = createContext();
// app.js
import React from 'react';
import { Store } from './context';
import Import from './import'; // I wouldn't change the casing on or reuse a reserved keyword personally, maybe calling this something like 'CsvImporter' would be an improvement
function App() {
const [dataDump, setDataDump] = React.useState([]);
return (
<Store.Provider value={{ dataDump, setDataDump }}>
<Import dataDump={dataDump} setDataDump={setDataDump} />
</Store.Provider>
);
}
Now your import component has two new props, dataDump and setDataDump. You can call setDataDump just like any other call to setting state. Nice!
So you need the dataDump in a new component? That's easy peasy, lemon squeezy, and all without global variables or tossing module scoping to the side:
// foobar.js
import React from 'react';
import { Store } from './context';
export function Foobar() {
// you probably want to do more than force render an array as a string, but this is just a proof of concept
return (
<Store.Consumer>
{({ dataDump, setDataDump }) => (
<p>
`${dataDump}`
</p>
)}
</Store.Consumer>
);
}
Just make sure that Foobar or other components are rendered as children of the Provider in app.js and now you have a 'global' context for passing around dataDumps.

How can pass a props to a variable?

I'm trying "hydrate" props from elements to child components that will render. The problem is that I can't figure out how I can do it with my configuration.
I have seen this answer, I tried to adapt it, but so far I'm getting errors (see bottom).
For a bit of background, I'm developing a Rails based application that uses React for the front end. So I don't use React router or such, it just "displays" the datas.
Here is how I set everything up:
front.js (where everything gets rendered)
import React from 'react';
import ReactDOM from 'react-dom';
import extractActionName from './lib/extractActionName';
import {elementForActionName} from './lib/elementForActionName';
import 'jquery';
import 'popper.js';
import 'bootstrap';
let actionName = extractActionName();
let value = "value";
let renderElement = function (Element, id) {
ReactDOM.render(
<Element value={value} />,
document.getElementById(id)
);
};
renderElement(elementForActionName[actionName], actionName);
lib/elementForActionName.js
import React from 'react';
import Homeindex from '../home/home';
import Contact from '../home/contact';
// This files create an associative array with id React will be
// looking for as a key and the component as value
export const elementForActionName = {
'index': <Homeindex />,
'contact': <Contact/>,
};
lib/extractActionName.js
export default function extractActionName() {
// The body contains classes such as "home index", so
// I return the "action name" of my controller (home) to
// front.js so I will render the good component
return document.body.className.split(' ').pop();
}
home/home.js
import React from 'react';
import Header from '../layout/header';
import Footer from '../layout/footer';
export default class homeIndex extends React.Component {
render() {
return(
<div>
<Header/>
<h1>Hello this will be the content of the landing page hello</h1>
<Footer/>
</div>
)
}
}
My problem is that I'd like to make an Ajax call in my "front.js" file, then transmit the received data (here, "value"). The error I'm getting is the following:
Uncaught Error: Element type is invalid: expected a string (for
built-in components) or a class/function (for composite components)
but got: object.
I'm lacking experience with React, how can I resolve this problem?
Thank you in advance.
You are currently returning the instance of a component:
export const elementForActionName = {
'index': <Homeindex />, <--- here
'contact': <Contact/>,
};
And then attempting to instantiate it again:
let renderElement = function (Element, id) {
ReactDOM.render(
<Element value={value} />, // <--- here
document.getElementById(id)
);
};
Instead, just use the component class:
export const elementForActionName = {
'index': Homeindex,
'contact': Contact,
};

how to get data from graphql server using react and react-apollo?

After about 6-8 hours trying, I'm resorting to help.
All I want is to query my graphql server and the response data to be entered into my react component as props (See ParameterBox.js). Please let me know what I'm doing wrong.
For Reference: INDEX.JS FILE (Likely correct)
import React from 'react';
import ReactDOM from 'react-dom';
import {
ApolloClient,
createNetworkInterface,
ApolloProvider,
} from 'react-apollo';
import App from './App';
const networkInterface = createNetworkInterface({
uri: 'http://localhost:3001/graphql'
});
const client = new ApolloClient({
networkInterface: networkInterface
});
ReactDOM.render(
<ApolloProvider client={client}>
<App />
</ApolloProvider>,
document.getElementById('root')
);
For Reference: APP.JS FILE (I think it's correct)
//App.js
import React, { Component } from 'react';
import ParameterBox from './ParameterBox';
class App extends Component {
render(){
return(
<div>
<ParameterBox />
</div>
)
}
}
export default App;
PARAMETERBOX.JS FILE (Here is where the issue is, somewhere...)
//ParameterBox.js
import React, { Component } from 'react';
import axios from 'axios';
import { gql, graphql } from 'react-apollo';
import ParameterList from './ParameterList';
class ParameterBox extends Component {
constructor (props) {
super(props);
this.state = { data: [] };
this.loadParamsFromServer = this.loadParamsFromServer.bind(this);
}
//*** Old Method ***/
// I still set my data using the old methods of API urls. I want to switch to GraphQL
loadParamsFromServer(){
axios.get('http://localhost:3001/api/params')
.then (res => {
this.setState({ data: res.data });
})
}
//**** end old method ****/
componentDidMount() {
this.loadParamsFromServer();
}
render(){
return(
<div >
<h2> Parameters: </h2>
<p> HOW DO I GET IT HERE? {this.props.AllParamsQuery } </p>
<ParameterList
data={ this.state.data }/>
</div>
)
}
}
const AllParams = gql`
query AllParamsQuery {
params {
id,
param,
input
}
}`;
export default graphql(AllParams, {name: 'AllParamsQuery'})(ParameterBox);
You may find it helpful to review the Apollo documentation for basic queries here.
When you wrap your component with the graphql HOC, it will send your query to the server and then make the result available to your component as this.props.data. So, the result for your particular query would be found at this.props.data.params (the operation name, AllParamsQuery is not referenced inside the returned data).
The other thing to bear in mind is that the GraphQL is asynchronous, so while props.data will always be available, initially it will be empty. Your render logic will need to account for that fact by verifying that this.props.data.params is truthy before tyring to render it. You can also check whether the query is still in flight or has completed.
Edit: because you define a name property (AllParamsQuery) inside the config object you pass to graphql(), your query results will be available as that prop instead of data -- i.e. 'this.props.AllParamsQuery.params`.

React Maximum Callstack when adding component

I have a list component that is getting information from a local json file if I do something like the following everything works as expected.
import React from 'react';
import caseStudies from './case-studies.json';
import CaseStudyItem from './case-study-list';
const CaseStudyList = () => {
const caseStudyItems = caseStudies.map( caseStudy => {
console.log(caseStudy);
return (
<div key={caseStudy.name}>{caseStudy.name}</div>
);
});
return (
<ul>
{caseStudyItems}
</ul>
);
}
export default CaseStudyList;
The expected number of case studies is printed out with no problem.
If however I replace the div inside of the caseStudies.map statement with the following
<CaseStudyItem key={caseStudy.id} caseStudy={caseStudy} />
I get a "Maximum Callstack size exceed error" if I add a log statement in there it shows it spitting out hundred and hundreds of items. What would cause this?
In case its needed here is the CaseStudyItem component, which is just blank now for testing purposes.
import React from 'react';
const CaseStudyItem = () => {
return (
<div>case Study</div>
);
}
export default CaseStudyItem;
I think you are making new CaseStudyLists inside each CaseStudyList. This is because you (probably) import from the wrong file:
import CaseStudyItem from './case-study-list';
should perhaps be
import CaseStudyItem from './case-study-item';
When you import like this, you can name the imported variable whatever you want, so what you though was the CaseStudyItem component creator was actually the CaseStudyList component creator.

Correct way to update form states in React?

So I'm having a go at my first React app using create-react-app, and I'm trying to make a multi-stage form based on this GitHub project. In particular the AccountFields and Registration parts.
That project seems to have been written in a much older version of React, so I've had to try and update it - and this is what I have so far:
App.js:
import React, { Component } from 'react';
import './App.css';
import Activity from './Activity';
var stage1Values = {
activity_name : "test"
};
class App extends Component {
constructor(props) {
super(props);
this.state = {
step: 1
};
};
render() {
switch (this.state) {
case 1:
return <Activity fieldValues={stage1Values} />;
}
};
saveStage1Values(activity_name) {
stage1Values.activity_name = activity_name;
};
nextStep() {
this.setState({
step : this.state.step + 1
})
};
}
export default App;
Activity.js:
import React, { Component } from 'react';
class Activity extends Component {
render() {
return (
<div className="App">
<div>
<label>Activity Name</label>
<input type="text" ref="activity_name" defaultValue={this.props.stage1Values} />
<button onClick={this.nextStep}>Save & Continue</button>
</div>
</div>
);
};
nextStep(event) {
event.preventDefault();
// Get values via this.refs
this.props.saveStage1Values(this.refs.activity_name.getDOMNode().value);
this.props.nextStep();
}
}
export default Activity;
I've looked at a number of examples, and this seems to be the right approach to store the current state (to allow users to go back and forth between different parts of the form), and to then store the values from this stage. When I click the Save & Continue button, I get an error saying Cannot read property 'props' of null. I mean obviously this means this is null, but I'm unsure of how to fix it.
Am I approaching this the wrong way? Every example I find seems to have a completely different implementation. I come from an Apache-based background, so this approach in general I find very unusual!
the this in nextStep isn't pointing to Activity and just do like this
<button onClick={()=>this.nextStep()}>Save & Continue</button>
Bind this to nextStep function:
<button onClick={this.nextStep.bind(this)}>Save & Continue</button>
Or in the constructor:
constructor(props){
super(props);
this.nextSteps = this.nextSteps.bind(this);
}

Categories

Resources