The Census geographies follow a strict hierarchy. Doing this as a simple attribute join using a link table will be much faster than doing it as a spatial join, and, as you have discovered also more accurate. As Chris W points, centroid do not always fall inside a polygon (think of a crescent or donut shape), and this is why you are ending up with incorrect matches.
The Census Bureau provides this data in the Census Block Assignment Files. Unfortunately this download page requires you to download the BAF by state. I was not able to find it in one national file, although I would not be surprised if someone has already done that somewhere. Also, if you already have an entire Census database somewhere, you could extract the relationships yourself from the GEOHEADER table.
When you download a state, you will get a ZIP with 9 files, each one being a table linking from the blocks to a specific geography. The ones you will be interested in are the ones ending in SLDU and SLDL which stand for State Legislative District Upper/Lower. The head of the SLDU for Iowa looks like this:
BLOCKID,DISTRICT
190019601001000,029
190019601001001,029
190019601001002,029
190019601001003,029
190019601001004,029
It's not completely clear from your question if your goal is to have a spatial output of the blocks with attached legislative districts, or if you were just using QGIS to do a spatial join because you couldn't find the BAF. In any event, from your question, it is clear that you have the knowledge to do the join on your own, so I am not going to elaborate unless you need additional assistance.